Update On Sat May 4 20:29:57 CEST 2024

This commit is contained in:
github-action[bot]
2024-05-04 20:29:58 +02:00
parent 3b93444c52
commit e48c8c4fe3
120 changed files with 1379 additions and 8934 deletions

1
.github/update.log vendored
View File

@@ -636,3 +636,4 @@ Update On Tue Apr 30 20:31:38 CEST 2024
Update On Wed May 1 20:30:48 CEST 2024 Update On Wed May 1 20:30:48 CEST 2024
Update On Thu May 2 20:28:05 CEST 2024 Update On Thu May 2 20:28:05 CEST 2024
Update On Fri May 3 20:27:51 CEST 2024 Update On Fri May 3 20:27:51 CEST 2024
Update On Sat May 4 20:29:46 CEST 2024

View File

@@ -238,6 +238,24 @@ func (blk *BrookLink) CreateExchanger(network, src string, dstb []byte, tcptimeo
} }
return sc, rc, nil return sc, rc, nil
} }
if blk.V.Get("udpoverstream") == "true" {
rc, err := QUICDialTCP(src, socks5.ToAddress(dstb[0], dstb[1:len(dstb)-2], dstb[len(dstb)-2:]), blk.Address, blk.Tc, tcptimeout)
if err != nil {
return nil, nil, err
}
var sc Exchanger
if blk.V.Get("withoutBrookProtocol") != "true" {
sc, err = NewStreamClient("udp", blk.Password, src, rc, tcptimeout, dstb)
}
if blk.V.Get("withoutBrookProtocol") == "true" {
sc, err = NewSimpleStreamClient("udp", blk.Password, src, rc, tcptimeout, dstb)
}
if err != nil {
rc.Close()
return nil, nil, err
}
return sc, rc, nil
}
rc, err := QUICDialUDP(src, socks5.ToAddress(dstb[0], dstb[1:len(dstb)-2], dstb[len(dstb)-2:]), blk.Address, blk.Tc, udptimeout) rc, err := QUICDialUDP(src, socks5.ToAddress(dstb[0], dstb[1:len(dstb)-2], dstb[len(dstb)-2:]), blk.Address, blk.Tc, udptimeout)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err

View File

@@ -74,7 +74,7 @@ func main() {
}, },
&cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "tag", Name: "tag",
Usage: "Tag can be used to the process, will be append into log or serverLog, such as: 'key1:value1'", Usage: "Tag can be used to the process, will be append into log or serverLog, such as: 'key1:value1'. All tags will also be appended as query parameters one by one to the userAPI",
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "dialWithDNS", Name: "dialWithDNS",
@@ -1583,6 +1583,10 @@ func main() {
Name: "udpovertcp", Name: "udpovertcp",
Usage: "When server is brook server, UDP over TCP", Usage: "When server is brook server, UDP over TCP",
}, },
&cli.BoolFlag{
Name: "udpoverstream",
Usage: "When server is brook quicserver, UDP over Stream. Note: only brook CLI and tun2brook suppport for now",
},
&cli.StringFlag{ &cli.StringFlag{
Name: "address", Name: "address",
Usage: "When server is brook wsserver or brook wssserver or brook quicserver, specify address instead of resolving addresses from host, such as 1.2.3.4:443", Usage: "When server is brook wsserver or brook wssserver or brook quicserver, specify address instead of resolving addresses from host, such as 1.2.3.4:443",
@@ -1613,11 +1617,11 @@ func main() {
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "fragment", Name: "fragment",
Usage: "When server is brook wssserver, split the ClientHello into multiple fragments and then send them one by one with delays (millisecond). The format is min_length:max_length:min_delay:max_delay, cannot be zero, such as 50:100:10:50, Note that: This is an experimental feature, currently only supported by the brook CLI and tun2brook", Usage: "When server is brook wssserver, split the ClientHello into multiple fragments and then send them one by one with delays (millisecond). The format is min_length:max_length:min_delay:max_delay, cannot be zero, such as 50:100:10:50",
}, },
&cli.StringFlag{ &cli.StringFlag{
Name: "token", Name: "token",
Usage: "A token represents a user's identity. A string encoded in hexadecimal. Server needs to have --userAPI enabled. Note that: Only supported by the brook GUI and tun2brook", Usage: "A token represents a user's identity. A string encoded in hexadecimal. Server needs to have --userAPI enabled. Note that: Only supported by the brook GUI(except for OpenWrt) and tun2brook",
}, },
&cli.BoolFlag{ &cli.BoolFlag{
Name: "example", Name: "example",
@@ -1656,6 +1660,9 @@ func main() {
if c.Bool("udpovertcp") { if c.Bool("udpovertcp") {
v.Set("udpovertcp", "true") v.Set("udpovertcp", "true")
} }
if c.Bool("udpoverstream") {
v.Set("udpoverstream", "true")
}
if c.String("address") != "" { if c.String("address") != "" {
v.Set("address", c.String("address")) v.Set("address", c.String("address"))
} }
@@ -2735,11 +2742,11 @@ func main() {
if ip == nil { if ip == nil {
return errors.New(c.String("ip") + " is not IP") return errors.New(c.String("ip") + " is not IP")
} }
b := iploc.Country(ip) s := iploc.Country(ip)
if b == nil { if s == "" {
return errors.New(c.String("ip") + " unknown") return errors.New(c.String("ip") + " unknown")
} }
fmt.Println(string(b)) fmt.Println(s)
return nil return nil
}, },
}, },

View File

@@ -6,7 +6,7 @@ echo '<!--G-R3M673HK5V-->' >> ../readme.md
echo 'A cross-platform programmable network tool.' >> ../readme.md echo 'A cross-platform programmable network tool.' >> ../readme.md
echo '' >> ../readme.md echo '' >> ../readme.md
echo '# Sponsor' >> ../readme.md echo '# Sponsor' >> ../readme.md
echo '**❤️ [Shiliew - China Optimized Network App](https://www.txthinking.com/shiliew.html)**' >> ../readme.md echo '**❤️ [Shiliew - A network app designed for those who value their time](https://www.txthinking.com/shiliew.html)**' >> ../readme.md
cat getting-started.md >> ../readme.md cat getting-started.md >> ../readme.md
cat gui.md >> ../readme.md cat gui.md >> ../readme.md
@@ -16,7 +16,6 @@ echo '# CLI Documentation' >> ../readme.md
jb '$1`brook mdpage`.split("\n").filter(v=>!v.startsWith("[")).join("\n").replace("```\n```", "```\nbrook --help\n```").split("\n").forEach(v=> echo(v.startsWith("**") && !v.startsWith("**Usage") ? "- "+v : v))' >> ../readme.md jb '$1`brook mdpage`.split("\n").filter(v=>!v.startsWith("[")).join("\n").replace("```\n```", "```\nbrook --help\n```").split("\n").forEach(v=> echo(v.startsWith("**") && !v.startsWith("**Usage") ? "- "+v : v))' >> ../readme.md
cat example.md >> ../readme.md cat example.md >> ../readme.md
cat diagram.md >> ../readme.md
markdown ../readme.md ./index.html markdown ../readme.md ./index.html

View File

@@ -1,40 +0,0 @@
# Diagram
> Maybe outdated
## overview
![overview](https://txthinking.github.io/brook/svg/overview.svg)
## withoutBrookProtocol
![wbp](https://txthinking.github.io/brook/svg/wbp.svg)
## relayoverbrook
![relayoverbrook](https://txthinking.github.io/brook/svg/relayoverbrook.svg)
## dnsserveroverbrook
![dnsserveroverbrook](https://txthinking.github.io/brook/svg/dnsserveroverbrook.svg)
## relay
![relay](https://txthinking.github.io/brook/svg/relay.svg)
## dnsserver
![dnsserver](https://txthinking.github.io/brook/svg/dnsserver.svg)
## tproxy
![tproxy](https://txthinking.github.io/brook/svg/tproxy.svg)
## gui
![gui](https://txthinking.github.io/brook/svg/gui.svg)
## script
![script](https://txthinking.github.io/brook/svg/script.svg)

View File

@@ -27,6 +27,6 @@
| [Socks5 Configurator](https://chromewebstore.google.com/detail/socks5-configurator/hnpgnjkeaobghpjjhaiemlahikgmnghb) | If you prefer CLI brook client | | [Socks5 Configurator](https://chromewebstore.google.com/detail/socks5-configurator/hnpgnjkeaobghpjjhaiemlahikgmnghb) | If you prefer CLI brook client |
| [IPvBar](https://chromewebstore.google.com/detail/ipvbar/nepjlegfiihpkcdhlmaebfdfppckonlj) | See domain, IP and country in browser | | [IPvBar](https://chromewebstore.google.com/detail/ipvbar/nepjlegfiihpkcdhlmaebfdfppckonlj) | See domain, IP and country in browser |
| [TxThinking SSH](https://www.txthinking.com/ssh.html) | A SSH Terminal | | [TxThinking SSH](https://www.txthinking.com/ssh.html) | A SSH Terminal |
| [brook-manager](https://github.com/txthinking/brook-manager) | Brook Manager is a Brook management system for medium to large merchants | | [brook-dashboard](https://github.com/txthinkinginc/brook-dashboard) | A Brook User System |
| [TxThinking](https://www.txthinking.com) | Everything | | [TxThinking](https://www.txthinking.com) | Everything |

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 31 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 36 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 50 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 44 KiB

View File

@@ -1,845 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" d2Version="v0.3.0" preserveAspectRatio="xMinYMin meet" viewBox="0 0 711 968"><svg id="d2-svg" class="d2-3723677766" width="711" height="968" viewBox="-101 -101 711 968"><rect x="-101.000000" y="-101.000000" width="711.000000" height="968.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><style type="text/css"><![CDATA[
.d2-3723677766 .text {
font-family: "d2-3723677766-font-regular";
}
@font-face {
font-family: d2-3723677766-font-regular;
src: url("data:application/font-woff;base64,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");
}
.d2-3723677766 .text-bold {
font-family: "d2-3723677766-font-bold";
}
@font-face {
font-family: d2-3723677766-font-bold;
src: url("data:application/font-woff;base64,d09GRgABAAAAAAuYAAoAAAAAEgAAAguFAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAAA9AAAAGAAAABgXxHXrmNtYXAAAAFUAAAAngAAANQEAQQ8Z2x5ZgAAAfQAAAVIAAAGwOLWr21oZWFkAAAHPAAAADYAAAA2G38e1GhoZWEAAAd0AAAAJAAAACQKfwXYaG10eAAAB5gAAABkAAAAZDGPBHVsb2NhAAAH/AAAADQAAAA0FZ4XbG1heHAAAAgwAAAAIAAAACAAMQD3bmFtZQAACFAAAAMoAAAIKgjwVkFwb3N0AAALeAAAAB0AAAAg/9EAMgADAioCvAAFAAACigJYAAAASwKKAlgAAAFeADIBKQAAAgsHAwMEAwICBGAAAvcAAAADAAAAAAAAAABBREJPACAAIP//Au7/BgAAA9gBESAAAZ8AAAAAAfAClAAAACAAA3ichM07DgFRAEbhc2eu93i/2gk9K5iKUiESCxChIhLR2IqC0KAVEp196DQ2YAG/5DZKp/6SAxh8DBBguQANQiweIU3aRHTp0WfIiDFT5ixYsmItgTMtIjrODJyZMPsZvfTRW089dNdNV5110lEH7bXTVht3/pehRoUqdTx8LDHiJEiSIk2GgCw58hQoUqIMXwAAAP//AQAA//8DFSwiAAB4nFyUT1AT5x/Gv++bZCNxATfJZhNCCMlLdkMwIWTZLD8gBjD8UZPwH+UHhJSxSgtEBmNxHK0HnR6cWGeEOtZDp+PIrT10vLQytjM9tGXGYx1PnbF/bs5Yxsn00ELS2V214uHNm8Pu836+z/O8CwYYAsBzeB10UAHVYAYWQGQ8jE8UBGKURVkmnE4WEGMcwubSxj2hUd/YqA/U33ZfmJ1FqQxe312cSs3N/TXb0VH67JsHpevo7AMABKFyEYfxbXACGLw8L7VGo2LExhl5nngpirXaxEhU5ig0M3JtdPz6SPykJ+2QycEjTRMD/rg9PUInP1la/HRY9GY4VyTTc3K5wTGdBQwpAJzEBTBppGLEZmOtFEUEMRKNSq08T0jq65M3h4duZIO1baOh0GhbLS4kbiwv3+xf9U+n05M+UPhSAOg3XACDqsJ42NQawriwu30RAF6eE8YFoMG65xzCMmJEalWOeTpwrq8v3zs8cL6rM4ELwvRgcq75FzQyLwb+0xjFBagC7g0No4UIqkpUk3nWu5KIS+sbl4aT7bFYexIXfCfSAzNc6Z9nz1C2JRzmFV5SLmITvg0B1U9Bttk0AUEI4b3mslYbx2m0yNp1OTJGJvyhoNg07unkO95LtC0HjtV3CXzwf4Gxjr72HB0OvVvHe11ul7mhqrmvOXqi9WBgxuF019bVMV77WG90ug0QOACwBRfAqExCJA9LmEf30d/38YGLF3e3QfX0SLmIB3EBGJVRYkRGjVn9Q6H05Y/W22W58+Mr9K17KFNayyaTWbRUunvvFmAIlIvoZ7QDDiAAnFcpjKyOYxTU4ViGCISi5EhUltT+fJsYurqGSaO7q0FqXmifPXXepHf373P4LOlON308nj5R7RHs7DuuhtxK6Q+xlqxwluOmJpedU1kbykX0EO1Azdv91BzU2kkhR++Z7oEPEqH+2l5SL8XjYXvI0u6boGPnRkbzsTpu1pXs7kqx1dl6p5a5ovsr2gE7uPcoq8l7lNQUXZ3YqhyE3P0rPYcXO/pnmvW49MTU1yJFW/jMnfvCQW+UPpQfGc7H4wsJi68iKnoma+pQe6PUrHltB0B5vKXsSh7yWx1gRZYw/+/paRg67G494KysoZ11k5Po0pLBKU200tSiweDh686Wriha3eUiMuOHUK05/yo3BfSnZMcaU2EwUmbaR08dw2T3CWdGaMlgVN4D0LnQDnjUdnOiRvAqLkYZ0fh671by6WuRui2eoy1Dx9Zc9b6w8tOMtrvcwSa/t2VhpvQIeaL+cOmrl5vmJzaiHah+60ui9lvQ7pCaGLLFzyQSZ+LxXCKRiwdDoWAoGHyZUyw/OnIutprq6k4qcYHGjm6gHTDvYdfc02CdSZ6tNdkrHQdqY1a0fTzSYjBc1usbI6WngIApF1EO55WbrXRdIpIsi4rrb5QHpgcTSebC6ipx0Q4TZ5Hp9ye2lqirV8/+GPBR+gWK1rKky4fQLtpWJuRe321Z1omczaaQybKoq8LnbZ7qGqN5n89vMn633r/fbNLvYyo6r3/BtQ1+T+mXkaHBVYN+f+zt85F+8ri0/9B4QNOPlYvwJ3wJ+1/dLCUgK3WLF0WeF0VaEvyS5Bck5dnKchZF8Q+gA+Asoq5yK7v1ue7Uzh2l214A9AJfA6fSbVEmkrZEo7pYoi4iE6NFlMmE7eh41eAUO2adZ8esg1OVY7PcuO005z1dNb+ZyWU2NjY2MrnM5uYmcuQAoFwGL9xFz9ELzIMd8kCBHQoqvxfZ0HP0ocJkkTysFz1Ctvl5APgXAAD//wEAAP//en1n1QABAAAAAguFLYoIq18PPPUAAQPoAAAAANhdoIQAAAAA3WYvNv43/sQIbQPxAAEAAwACAAAAAAAAAAEAAAPY/u8AAAiY/jf+NwhtAAEAAAAAAAAAAAAAAAAAAAAZArIAUADIAAACRgAuAnsATQIGAE0CVABNAmUATQIsACMCLAAZApkASQIPACoB0wAkAgYAJAFVABgBHgBBA1kAQQIrACQBjgBBAX8AEQIJAAwBLAA9AVMADQIQACICEAAiAhAAIgAAACwALABYAHwAjACuANQBFAEmAUQBfAGoAdwCAgIeAlACfAKcAsIC8gMIAxYDRgNSA2AAAQAAABkAkAAMAGMABwABAAAAAAAAAAAAAAAAAAQAA3icnJTPbhtVFMZ/TmzTCsECRVW6ie6CRZHo2FRJ1TYrh9SKRRQHjwtCQkgTz/iPMp4ZeSYO4QlY8xa8RVc8BM+BWKP5fOzYBdEmipJ8d+75851zvnOBHf5mm0r1IfBHPTFcYa9+bniLB/UTw9u061uGqzyp/Wm4RlibG67zea1n+CPeVn8z/ID96k+GH7JbbRv+mGfVHcOfbDv+Mvwp+7xd4Aq84FfDFXbJDG+xw4+Gt3mExaxUeUTTcI3P2DNcZw/oM6EgZkLCCMeQCSOumBGR4xMxY8KQiBBHhxYxhb4mBEKO0X9+DfApmBEo4pgCR4xPTEDO2CL+Iq+Uc2Uc6jSzuxYFYwIu5HFJQIIjZURKQsSl4hQUZLyiQYOcgfhmFOR45EyI8UiZMaJBlzan9BkzIcfRVqSSmU/KkIJrAuV3ZlF2ZkBEQm6srkgIxdOJXyTvDqc4umSyXY98uhHhSxzfybvklsr2Kzz9ujVmm3mXbALm6mesrsS6udYEx7ot87b4VrjgFe5e/dlk8v4ehfpfKPIFV5p/qEklYpLg3C4tfCnId49xHOncwVdHvqdDnxO6vKGvc4sePVqc0afDa/l26eH4mi5nHMujI7y4a0sxZ/yA4xs6siljR9afxcQifiYzdefiOFMdUzL1vGTuqdZIFd59wuUOpRvqyOUz0B6Vlk7zS7RnASNTRSaGU/VyqY3c+heaIqaqpZzt7X25DXPbveUW35Bqh0u1LjiVk1swet9UvXc0c60fj4CQlAtZDEiZ0qDgRrzPCbgixnGs7p1oSwpaK58yz41UEjEVgw6J4szI9Dcw3fjGfbChe2dvSSj/kunlqqr7ZHHq1e2M3qh7yzvfuhytTaBhU03X1DQQ18S0H2mn1vn78s31uqU85YiUmPBfL8AzPJrsc8AhY2UY6GZur0NTL0STlxyq+ksiWQ2l58giHODxnAMOeMnzd/q4ZOKMi1txWc/d4pgjuhx+UBUL+y5HvF59+/+sv4tpU7U4nq5OL+49xSd3UOsX2rPb97KniZWTmFu02604I2BacnG76zW5x3j/AAAA//8BAAD///S3T1F4nGJgZgCD/+cYjBiwAAAAAAD//wEAAP//LwECAwAAAA==");
}]]></style><style type="text/css"><![CDATA[.shape {
shape-rendering: geometricPrecision;
stroke-linejoin: round;
}
.connection {
stroke-linecap: round;
stroke-linejoin: round;
}
.blend {
mix-blend-mode: multiply;
opacity: 0.5;
}
.d2-3723677766 .fill-N1{fill:#0A0F25;}
.d2-3723677766 .fill-N2{fill:#676C7E;}
.d2-3723677766 .fill-N3{fill:#9499AB;}
.d2-3723677766 .fill-N4{fill:#CFD2DD;}
.d2-3723677766 .fill-N5{fill:#DEE1EB;}
.d2-3723677766 .fill-N6{fill:#EEF1F8;}
.d2-3723677766 .fill-N7{fill:#FFFFFF;}
.d2-3723677766 .fill-B1{fill:#0D32B2;}
.d2-3723677766 .fill-B2{fill:#0D32B2;}
.d2-3723677766 .fill-B3{fill:#E3E9FD;}
.d2-3723677766 .fill-B4{fill:#E3E9FD;}
.d2-3723677766 .fill-B5{fill:#EDF0FD;}
.d2-3723677766 .fill-B6{fill:#F7F8FE;}
.d2-3723677766 .fill-AA2{fill:#4A6FF3;}
.d2-3723677766 .fill-AA4{fill:#EDF0FD;}
.d2-3723677766 .fill-AA5{fill:#F7F8FE;}
.d2-3723677766 .fill-AB4{fill:#EDF0FD;}
.d2-3723677766 .fill-AB5{fill:#F7F8FE;}
.d2-3723677766 .stroke-N1{stroke:#0A0F25;}
.d2-3723677766 .stroke-N2{stroke:#676C7E;}
.d2-3723677766 .stroke-N3{stroke:#9499AB;}
.d2-3723677766 .stroke-N4{stroke:#CFD2DD;}
.d2-3723677766 .stroke-N5{stroke:#DEE1EB;}
.d2-3723677766 .stroke-N6{stroke:#EEF1F8;}
.d2-3723677766 .stroke-N7{stroke:#FFFFFF;}
.d2-3723677766 .stroke-B1{stroke:#0D32B2;}
.d2-3723677766 .stroke-B2{stroke:#0D32B2;}
.d2-3723677766 .stroke-B3{stroke:#E3E9FD;}
.d2-3723677766 .stroke-B4{stroke:#E3E9FD;}
.d2-3723677766 .stroke-B5{stroke:#EDF0FD;}
.d2-3723677766 .stroke-B6{stroke:#F7F8FE;}
.d2-3723677766 .stroke-AA2{stroke:#4A6FF3;}
.d2-3723677766 .stroke-AA4{stroke:#EDF0FD;}
.d2-3723677766 .stroke-AA5{stroke:#F7F8FE;}
.d2-3723677766 .stroke-AB4{stroke:#EDF0FD;}
.d2-3723677766 .stroke-AB5{stroke:#F7F8FE;}
.d2-3723677766 .background-color-N1{background-color:#0A0F25;}
.d2-3723677766 .background-color-N2{background-color:#676C7E;}
.d2-3723677766 .background-color-N3{background-color:#9499AB;}
.d2-3723677766 .background-color-N4{background-color:#CFD2DD;}
.d2-3723677766 .background-color-N5{background-color:#DEE1EB;}
.d2-3723677766 .background-color-N6{background-color:#EEF1F8;}
.d2-3723677766 .background-color-N7{background-color:#FFFFFF;}
.d2-3723677766 .background-color-B1{background-color:#0D32B2;}
.d2-3723677766 .background-color-B2{background-color:#0D32B2;}
.d2-3723677766 .background-color-B3{background-color:#E3E9FD;}
.d2-3723677766 .background-color-B4{background-color:#E3E9FD;}
.d2-3723677766 .background-color-B5{background-color:#EDF0FD;}
.d2-3723677766 .background-color-B6{background-color:#F7F8FE;}
.d2-3723677766 .background-color-AA2{background-color:#4A6FF3;}
.d2-3723677766 .background-color-AA4{background-color:#EDF0FD;}
.d2-3723677766 .background-color-AA5{background-color:#F7F8FE;}
.d2-3723677766 .background-color-AB4{background-color:#EDF0FD;}
.d2-3723677766 .background-color-AB5{background-color:#F7F8FE;}
.d2-3723677766 .color-N1{color:#0A0F25;}
.d2-3723677766 .color-N2{color:#676C7E;}
.d2-3723677766 .color-N3{color:#9499AB;}
.d2-3723677766 .color-N4{color:#CFD2DD;}
.d2-3723677766 .color-N5{color:#DEE1EB;}
.d2-3723677766 .color-N6{color:#EEF1F8;}
.d2-3723677766 .color-N7{color:#FFFFFF;}
.d2-3723677766 .color-B1{color:#0D32B2;}
.d2-3723677766 .color-B2{color:#0D32B2;}
.d2-3723677766 .color-B3{color:#E3E9FD;}
.d2-3723677766 .color-B4{color:#E3E9FD;}
.d2-3723677766 .color-B5{color:#EDF0FD;}
.d2-3723677766 .color-B6{color:#F7F8FE;}
.d2-3723677766 .color-AA2{color:#4A6FF3;}
.d2-3723677766 .color-AA4{color:#EDF0FD;}
.d2-3723677766 .color-AA5{color:#F7F8FE;}
.d2-3723677766 .color-AB4{color:#EDF0FD;}
.d2-3723677766 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]></style><style type="text/css">.md em,
.md dfn {
font-family: "d2-3723677766-font-italic";
}
.md b,
.md strong {
font-family: "d2-3723677766-font-bold";
}
.md code,
.md kbd,
.md pre,
.md samp {
font-family: "d2-3723677766-font-mono";
font-size: 1em;
}
.md {
tab-size: 4;
}
/* variables are provided in d2renderers/d2svg/d2svg.go */
.md {
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
margin: 0;
color: var(--color-fg-default);
background-color: transparent; /* we don't want to define the background color */
font-family: "d2-3723677766-font-regular";
font-size: 16px;
line-height: 1.5;
word-wrap: break-word;
}
.md details,
.md figcaption,
.md figure {
display: block;
}
.md summary {
display: list-item;
}
.md [hidden] {
display: none !important;
}
.md a {
background-color: transparent;
color: var(--color-accent-fg);
text-decoration: none;
}
.md a:active,
.md a:hover {
outline-width: 0;
}
.md abbr[title] {
border-bottom: none;
text-decoration: underline dotted;
}
.md dfn {
font-style: italic;
}
.md h1 {
margin: 0.67em 0;
font-weight: 600;
padding-bottom: 0.3em;
font-size: 2em;
border-bottom: 1px solid var(--color-border-muted);
}
.md mark {
background-color: var(--color-attention-subtle);
color: var(--color-text-primary);
}
.md small {
font-size: 90%;
}
.md sub,
.md sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
.md sub {
bottom: -0.25em;
}
.md sup {
top: -0.5em;
}
.md img {
border-style: none;
max-width: 100%;
box-sizing: content-box;
background-color: var(--color-canvas-default);
}
.md figure {
margin: 1em 40px;
}
.md hr {
box-sizing: content-box;
overflow: hidden;
background: transparent;
border-bottom: 1px solid var(--color-border-muted);
height: 0.25em;
padding: 0;
margin: 24px 0;
background-color: var(--color-border-default);
border: 0;
}
.md input {
font: inherit;
margin: 0;
overflow: visible;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
.md [type="button"],
.md [type="reset"],
.md [type="submit"] {
-webkit-appearance: button;
}
.md [type="button"]::-moz-focus-inner,
.md [type="reset"]::-moz-focus-inner,
.md [type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
.md [type="button"]:-moz-focusring,
.md [type="reset"]:-moz-focusring,
.md [type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
.md [type="checkbox"],
.md [type="radio"] {
box-sizing: border-box;
padding: 0;
}
.md [type="number"]::-webkit-inner-spin-button,
.md [type="number"]::-webkit-outer-spin-button {
height: auto;
}
.md [type="search"] {
-webkit-appearance: textfield;
outline-offset: -2px;
}
.md [type="search"]::-webkit-search-cancel-button,
.md [type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
.md ::-webkit-input-placeholder {
color: inherit;
opacity: 0.54;
}
.md ::-webkit-file-upload-button {
-webkit-appearance: button;
font: inherit;
}
.md a:hover {
text-decoration: underline;
}
.md hr::before {
display: table;
content: "";
}
.md hr::after {
display: table;
clear: both;
content: "";
}
.md table {
border-spacing: 0;
border-collapse: collapse;
display: block;
width: max-content;
max-width: 100%;
overflow: auto;
}
.md td,
.md th {
padding: 0;
}
.md details summary {
cursor: pointer;
}
.md details:not([open]) > *:not(summary) {
display: none !important;
}
.md kbd {
display: inline-block;
padding: 3px 5px;
color: var(--color-fg-default);
vertical-align: middle;
background-color: var(--color-canvas-subtle);
border: solid 1px var(--color-neutral-muted);
border-bottom-color: var(--color-neutral-muted);
border-radius: 6px;
box-shadow: inset 0 -1px 0 var(--color-neutral-muted);
}
.md h1,
.md h2,
.md h3,
.md h4,
.md h5,
.md h6 {
margin-top: 24px;
margin-bottom: 16px;
font-weight: 600;
line-height: 1.25;
font-family: "d2-3723677766-font-regular";
}
.md h2 {
font-weight: 600;
padding-bottom: 0.3em;
font-size: 1.5em;
border-bottom: 1px solid var(--color-border-muted);
}
.md h3 {
font-weight: 600;
font-size: 1.25em;
}
.md h4 {
font-weight: 600;
font-size: 1em;
}
.md h5 {
font-weight: 600;
font-size: 0.875em;
}
.md h6 {
font-weight: 600;
font-size: 0.85em;
color: var(--color-fg-muted);
}
.md p {
margin-top: 0;
margin-bottom: 10px;
}
.md blockquote {
margin: 0;
padding: 0 1em;
color: var(--color-fg-muted);
border-left: 0.25em solid var(--color-border-default);
}
.md ul,
.md ol {
margin-top: 0;
margin-bottom: 0;
padding-left: 2em;
}
.md ol ol,
.md ul ol {
list-style-type: lower-roman;
}
.md ul ul ol,
.md ul ol ol,
.md ol ul ol,
.md ol ol ol {
list-style-type: lower-alpha;
}
.md dd {
margin-left: 0;
}
.md pre {
margin-top: 0;
margin-bottom: 0;
word-wrap: normal;
}
.md ::placeholder {
color: var(--color-fg-subtle);
opacity: 1;
}
.md input::-webkit-outer-spin-button,
.md input::-webkit-inner-spin-button {
margin: 0;
-webkit-appearance: none;
appearance: none;
}
.md::before {
display: table;
content: "";
}
.md::after {
display: table;
clear: both;
content: "";
}
.md > *:first-child {
margin-top: 0 !important;
}
.md > *:last-child {
margin-bottom: 0 !important;
}
.md a:not([href]) {
color: inherit;
text-decoration: none;
}
.md .absent {
color: var(--color-danger-fg);
}
.md .anchor {
float: left;
padding-right: 4px;
margin-left: -20px;
line-height: 1;
}
.md .anchor:focus {
outline: none;
}
.md p,
.md blockquote,
.md ul,
.md ol,
.md dl,
.md table,
.md pre,
.md details {
margin-top: 0;
margin-bottom: 16px;
}
.md blockquote > :first-child {
margin-top: 0;
}
.md blockquote > :last-child {
margin-bottom: 0;
}
.md sup > a::before {
content: "[";
}
.md sup > a::after {
content: "]";
}
.md h1:hover .anchor,
.md h2:hover .anchor,
.md h3:hover .anchor,
.md h4:hover .anchor,
.md h5:hover .anchor,
.md h6:hover .anchor {
text-decoration: none;
}
.md h1 tt,
.md h1 code,
.md h2 tt,
.md h2 code,
.md h3 tt,
.md h3 code,
.md h4 tt,
.md h4 code,
.md h5 tt,
.md h5 code,
.md h6 tt,
.md h6 code {
padding: 0 0.2em;
font-size: inherit;
}
.md ul.no-list,
.md ol.no-list {
padding: 0;
list-style-type: none;
}
.md ol[type="1"] {
list-style-type: decimal;
}
.md ol[type="a"] {
list-style-type: lower-alpha;
}
.md ol[type="i"] {
list-style-type: lower-roman;
}
.md div > ol:not([type]) {
list-style-type: decimal;
}
.md ul ul,
.md ul ol,
.md ol ol,
.md ol ul {
margin-top: 0;
margin-bottom: 0;
}
.md li > p {
margin-top: 16px;
}
.md li + li {
margin-top: 0.25em;
}
.md dl {
padding: 0;
}
.md dl dt {
padding: 0;
margin-top: 16px;
font-size: 1em;
font-style: italic;
font-weight: 600;
}
.md dl dd {
padding: 0 16px;
margin-bottom: 16px;
}
.md table th {
font-weight: 600;
}
.md table th,
.md table td {
padding: 6px 13px;
border: 1px solid var(--color-border-default);
}
.md table tr {
background-color: var(--color-canvas-default);
border-top: 1px solid var(--color-border-muted);
}
.md table tr:nth-child(2n) {
background-color: var(--color-canvas-subtle);
}
.md table img {
background-color: transparent;
}
.md img[align="right"] {
padding-left: 20px;
}
.md img[align="left"] {
padding-right: 20px;
}
.md span.frame {
display: block;
overflow: hidden;
}
.md span.frame > span {
display: block;
float: left;
width: auto;
padding: 7px;
margin: 13px 0 0;
overflow: hidden;
border: 1px solid var(--color-border-default);
}
.md span.frame span img {
display: block;
float: left;
}
.md span.frame span span {
display: block;
padding: 5px 0 0;
clear: both;
color: var(--color-fg-default);
}
.md span.align-center {
display: block;
overflow: hidden;
clear: both;
}
.md span.align-center > span {
display: block;
margin: 13px auto 0;
overflow: hidden;
text-align: center;
}
.md span.align-center span img {
margin: 0 auto;
text-align: center;
}
.md span.align-right {
display: block;
overflow: hidden;
clear: both;
}
.md span.align-right > span {
display: block;
margin: 13px 0 0;
overflow: hidden;
text-align: right;
}
.md span.align-right span img {
margin: 0;
text-align: right;
}
.md span.float-left {
display: block;
float: left;
margin-right: 13px;
overflow: hidden;
}
.md span.float-left span {
margin: 13px 0 0;
}
.md span.float-right {
display: block;
float: right;
margin-left: 13px;
overflow: hidden;
}
.md span.float-right > span {
display: block;
margin: 13px auto 0;
overflow: hidden;
text-align: right;
}
.md code,
.md tt {
padding: 0.2em 0.4em;
margin: 0;
font-size: 85%;
background-color: var(--color-neutral-muted);
border-radius: 6px;
}
.md code br,
.md tt br {
display: none;
}
.md del code {
text-decoration: inherit;
}
.md pre code {
font-size: 100%;
}
.md pre > code {
padding: 0;
margin: 0;
word-break: normal;
white-space: pre;
background: transparent;
border: 0;
}
.md .highlight {
margin-bottom: 16px;
}
.md .highlight pre {
margin-bottom: 0;
word-break: normal;
}
.md .highlight pre,
.md pre {
padding: 16px;
overflow: auto;
font-size: 85%;
line-height: 1.45;
background-color: var(--color-canvas-subtle);
border-radius: 6px;
}
.md pre code,
.md pre tt {
display: inline;
max-width: auto;
padding: 0;
margin: 0;
overflow: visible;
line-height: inherit;
word-wrap: normal;
background-color: transparent;
border: 0;
}
.md .csv-data td,
.md .csv-data th {
padding: 5px;
overflow: hidden;
font-size: 12px;
line-height: 1;
text-align: left;
white-space: nowrap;
}
.md .csv-data .blob-num {
padding: 10px 8px 9px;
text-align: right;
background: var(--color-canvas-default);
border: 0;
}
.md .csv-data tr {
border-top: 0;
}
.md .csv-data th {
font-weight: 600;
background: var(--color-canvas-subtle);
border-top: 0;
}
.md .footnotes {
font-size: 12px;
color: var(--color-fg-muted);
border-top: 1px solid var(--color-border-default);
}
.md .footnotes ol {
padding-left: 16px;
}
.md .footnotes li {
position: relative;
}
.md .footnotes li:target::before {
position: absolute;
top: -8px;
right: -8px;
bottom: -8px;
left: -24px;
pointer-events: none;
content: "";
border: 2px solid var(--color-accent-emphasis);
border-radius: 6px;
}
.md .footnotes li:target {
color: var(--color-fg-default);
}
.md .task-list-item {
list-style-type: none;
}
.md .task-list-item label {
font-weight: 400;
}
.md .task-list-item.enabled label {
cursor: pointer;
}
.md .task-list-item + .task-list-item {
margin-top: 3px;
}
.md .task-list-item .handle {
display: none;
}
.md .task-list-item-checkbox {
margin: 0 0.2em 0.25em -1.6em;
vertical-align: middle;
}
.md .contains-task-list:dir(rtl) .task-list-item-checkbox {
margin: 0 -1.6em 0.25em 0.2em;
}
</style><g id="description"><g class="shape" ></g><g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="0.000000" y="8.000000" width="309" height="51"><div xmlns="http://www.w3.org/1999/xhtml" class="md"><h1>relay.from == relay.to</h1>
</div></foreignObject></g></g><g id="Local/TCP/UDP"><g class="shape" ><path d="M 344 195 C 344 196 343 197 342 197 C 326 198 314 209 314 223 C 314 238 328 250 345 250 H 464 C 483 250 498 237 498 222 C 498 207 484 195 466 194 C 465 194 464 193 463 192 C 459 177 441 166 419 166 C 405 166 392 171 384 178 C 383 179 382 179 381 179 C 378 178 375 178 371 178 C 357 178 345 185 344 195 Z" class=" stroke-B1 fill-N7" style="stroke-width:2;" /></g><text x="404.757500" y="229.516000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Local/TCP/UDP</text></g><g id="Remote/TCP/UDP"><g class="shape" ><path d="M 337 545 C 337 546 336 547 334 547 C 317 548 303 559 303 573 C 303 588 318 600 338 600 H 471 C 492 600 509 587 509 572 C 509 557 493 545 473 544 C 472 544 470 543 470 542 C 466 527 445 516 421 516 C 405 516 391 521 382 528 C 381 529 379 529 378 529 C 375 528 371 528 367 528 C 351 528 338 535 337 545 Z" class=" stroke-B1 fill-N7" style="stroke-width:2;" /></g><text x="405.357000" y="579.516000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Remote/TCP/UDP</text></g><g id="SRC"><g class="shape" ><rect x="369.000000" y="0.000000" width="73.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="405.500000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">SRC</text></g><g id="&#34;relay.from&#34;"><g class="shape" ><rect x="346.000000" y="350.000000" width="119.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="405.500000" y="388.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">relay.from</text></g><g id="&#34;relay.to&#34;"><g class="shape" ><rect x="356.000000" y="700.000000" width="100.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="406.000000" y="738.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">relay.to</text></g><g id="(SRC -&gt; Local/TCP/UDP)[0]"><marker id="mk-3488378134" markerWidth="10.000000" markerHeight="12.000000" refX="7.000000" refY="6.000000" viewBox="0.000000 0.000000 10.000000 12.000000" orient="auto" markerUnits="userSpaceOnUse"> <polygon points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" class="connection fill-B1" stroke-width="2" /> </marker><path d="M 405.500000 68.000000 C 405.500000 106.000000 405.600000 126.400000 405.961540 164.000185" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-3723677766)" /></g><g id="(Local/TCP/UDP -&gt; &#34;relay.from&#34;)[0]"><path d="M 405.980001 251.999900 C 405.600000 290.000000 405.500000 310.000000 405.500000 346.000000" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-3723677766)" /></g><g id="(&#34;relay.from&#34; -&gt; Remote/TCP/UDP)[0]"><path d="M 405.500000 418.000000 C 405.500000 456.000000 405.600000 476.400000 405.961540 514.000185" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-3723677766)" /></g><g id="(Remote/TCP/UDP -&gt; &#34;relay.to&#34;)[0]"><path d="M 405.980001 601.999900 C 405.600000 640.000000 405.500000 660.000000 405.500000 696.000000" fill="none" class="connection stroke-B1" style="stroke-width:2;" marker-end="url(#mk-3488378134)" mask="url(#d2-3723677766)" /></g><mask id="d2-3723677766" maskUnits="userSpaceOnUse" x="-101" y="-101" width="711" height="968">
<rect x="-101" y="-101" width="711" height="968" fill="white"></rect>
</mask></svg></svg>

Before

Width:  |  Height:  |  Size: 28 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 33 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 64 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 53 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 37 KiB

View File

@@ -8,7 +8,7 @@ require (
github.com/krolaw/dhcp4 v0.0.0-20190909130307-a50d88189771 github.com/krolaw/dhcp4 v0.0.0-20190909130307-a50d88189771
github.com/miekg/dns v1.1.57 github.com/miekg/dns v1.1.57
github.com/patrickmn/go-cache v2.1.0+incompatible github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/phuslu/iploc v1.0.20231031 github.com/phuslu/iploc v1.0.20240501
github.com/prometheus/client_golang v1.17.0 github.com/prometheus/client_golang v1.17.0
github.com/quic-go/quic-go v0.42.0 github.com/quic-go/quic-go v0.42.0
github.com/refraction-networking/utls v1.5.4 github.com/refraction-networking/utls v1.5.4

View File

@@ -51,6 +51,8 @@ github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaR
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/phuslu/iploc v1.0.20231031 h1:AsKT2PqStXV+gqJjNJ5mcUJ7YT9i09W+NVthhz5987s= github.com/phuslu/iploc v1.0.20231031 h1:AsKT2PqStXV+gqJjNJ5mcUJ7YT9i09W+NVthhz5987s=
github.com/phuslu/iploc v1.0.20231031/go.mod h1:gsgExGWldwv1AEzZm+Ki9/vGfyjkL33pbSr9HGpt2Xg= github.com/phuslu/iploc v1.0.20231031/go.mod h1:gsgExGWldwv1AEzZm+Ki9/vGfyjkL33pbSr9HGpt2Xg=
github.com/phuslu/iploc v1.0.20240501 h1:lX2dEFOQzxVpTH3dgJ+pcNEpLxwaJUhoCGMoajuAI5w=
github.com/phuslu/iploc v1.0.20240501/go.mod h1:VZqAWoi2A80YPvfk1AizLGHavNIG9nhBC8d87D/SeVs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=

View File

@@ -71,9 +71,8 @@ func ListHasIP(c4, c6 []*net.IPNet, i net.IP, c *cache.Cache, geo []string) bool
} }
} }
if len(geo) != 0 { if len(geo) != 0 {
b := iploc.Country(i) bs := iploc.Country(i)
if b != nil { if bs != "" {
bs := string(b)
for _, v := range geo { for _, v := range geo {
if v == bs { if v == bs {
if c != nil { if c != nil {

View File

@@ -1,7 +1,5 @@
# User System # User System
⚠️ Currently, this feature is experimental. At present, only this [brook_linux_amd64.20240606](https://github.com/txthinking/bash/releases/download/v20221005/brook_linux_amd64.20240606) and [tun2brook](https://github.com/txthinking/tun2brook) support it.
This content introduces how to develop a user system with Brook. Your system only needs to focus on two concepts: **Token** and **User API**. To support user system, you **must use brook server/wsserver/wssserver/quicserver with the brook protocol**. This content introduces how to develop a user system with Brook. Your system only needs to focus on two concepts: **Token** and **User API**. To support user system, you **must use brook server/wsserver/wssserver/quicserver with the brook protocol**.
<img src="https://brook.app/images/user-system.png" width="500"> <img src="https://brook.app/images/user-system.png" width="500">
@@ -14,14 +12,14 @@ For example, encrypt user id or make session, and encode in hexadecimal:
``` ```
hex_encode(your_encrypt_or_session_function(user id)) hex_encode(your_encrypt_or_session_function(user id))
// 3ae6afc9fad94abd8985d8ecc77afb273ae6afc9fad94abd8985d8ecc77afb273ae6afc9fad94abd8985d8ecc77afb27 // 48 bytes token // 3ae6afc9fad94abd8985d8ecc77afb273ae6afc9fad94abd8985d8ecc77afb273ae6afc9fad94abd8985d8ecc77afb27
``` ```
For example, UUID: For example, UUID:
```javascript ```javascript
crypto.randomUUID().replaceAll('-', '') crypto.randomUUID().replaceAll('-', '')
// 3ae6afc9fad94abd8985d8ecc77afb27 // 16 bytes token // 3ae6afc9fad94abd8985d8ecc77afb27
``` ```
## User API ## User API
@@ -79,3 +77,6 @@ You can count the traffic of each user from serverLog
brook link --server 1.2.3.4:9999 --password hello --token xxx brook link --server 1.2.3.4:9999 --password hello --token xxx
``` ```
## Basic reference implementation
https://github.com/TxThinkingInc/brook-dashboard

View File

@@ -148,8 +148,15 @@ func (s *QUICServer) ListenAndServe() error {
return return
} }
defer ss.Clean() defer ss.Clean()
if err := s.TCPHandle(ss); err != nil { if ss.Network() == "tcp" {
Log(Error{"from": ss.Src(), "dst": ss.Dst(), "error": err.Error()}) if err := s.TCPHandle(ss); err != nil {
Log(Error{"from": ss.Src(), "dst": ss.Dst(), "error": err.Error()})
}
}
if ss.Network() == "udp" {
if err := s.UDPOverTCPHandle(ss); err != nil {
Log(Error{"from": c.RemoteAddr().String(), "dst": ss.Dst(), "error": err.Error()})
}
} }
}(&QUICConn{ }(&QUICConn{
Conn: c, Conn: c,
@@ -240,6 +247,18 @@ func (s *QUICServer) TCPHandle(ss Exchanger) error {
return nil return nil
} }
func (s *QUICServer) UDPOverTCPHandle(ss Exchanger) error {
rc, err := NATDial("udp", ss.Src(), ss.Dst(), ss.Dst())
if err != nil {
return err
}
defer rc.Close()
if err := ss.Exchange(rc); err != nil {
return nil
}
return nil
}
func (s *QUICServer) UDPHandle(ss Exchanger) error { func (s *QUICServer) UDPHandle(ss Exchanger) error {
rc, err := NATDial("udp", ss.Src(), ss.Dst(), ss.Dst()) rc, err := NATDial("udp", ss.Src(), ss.Dst(), ss.Dst())
if err != nil { if err != nil {

View File

@@ -16,10 +16,12 @@ package brook
import ( import (
"log" "log"
"net"
"testing" "testing"
"github.com/phuslu/iploc"
) )
func TestTest(t *testing.T) { func TestTest(t *testing.T) {
l, err := CAC("/tmp/a") log.Printf("%#v\n", iploc.Country(net.ParseIP("8.8.8.8")))
log.Printf("%#v %v\n", l, err)
} }

View File

@@ -98,4 +98,3 @@ API.
This software is released under the GPL-3.0 license. This software is released under the GPL-3.0 license.
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FMetaCubeX%2Fmihomo.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2FMetaCubeX%2Fmihomo?ref=badge_large)

View File

@@ -35,7 +35,7 @@
"react-dom": "18.3.1", "react-dom": "18.3.1",
"react-error-boundary": "4.0.13", "react-error-boundary": "4.0.13",
"react-fast-marquee": "1.6.4", "react-fast-marquee": "1.6.4",
"react-hook-form": "7.51.3", "react-hook-form": "7.51.4",
"react-i18next": "14.1.1", "react-i18next": "14.1.1",
"react-markdown": "9.0.1", "react-markdown": "9.0.1",
"react-router-dom": "6.23.0", "react-router-dom": "6.23.0",

View File

@@ -97,7 +97,7 @@
"stylelint-config-standard": "36.0.0", "stylelint-config-standard": "36.0.0",
"stylelint-declaration-block-no-ignored-properties": "2.8.0", "stylelint-declaration-block-no-ignored-properties": "2.8.0",
"stylelint-order": "6.0.4", "stylelint-order": "6.0.4",
"stylelint-scss": "6.2.1", "stylelint-scss": "6.3.0",
"tailwindcss": "3.4.3", "tailwindcss": "3.4.3",
"tsx": "4.9.0", "tsx": "4.9.0",
"typescript": "5.4.5" "typescript": "5.4.5"

View File

@@ -121,8 +121,8 @@ importers:
specifier: 6.0.4 specifier: 6.0.4
version: 6.0.4(stylelint@16.5.0(typescript@5.4.5)) version: 6.0.4(stylelint@16.5.0(typescript@5.4.5))
stylelint-scss: stylelint-scss:
specifier: 6.2.1 specifier: 6.3.0
version: 6.2.1(stylelint@16.5.0(typescript@5.4.5)) version: 6.3.0(stylelint@16.5.0(typescript@5.4.5))
tailwindcss: tailwindcss:
specifier: 3.4.3 specifier: 3.4.3
version: 3.4.3 version: 3.4.3
@@ -226,8 +226,8 @@ importers:
specifier: 1.6.4 specifier: 1.6.4
version: 1.6.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) version: 1.6.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react-hook-form: react-hook-form:
specifier: 7.51.3 specifier: 7.51.4
version: 7.51.3(react@18.3.1) version: 7.51.4(react@18.3.1)
react-i18next: react-i18next:
specifier: 14.1.1 specifier: 14.1.1
version: 14.1.1(i18next@23.11.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) version: 14.1.1(i18next@23.11.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -2127,8 +2127,8 @@ packages:
eastasianwidth@0.2.0: eastasianwidth@0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
electron-to-chromium@1.4.754: electron-to-chromium@1.4.756:
resolution: {integrity: sha512-7Kr5jUdns5rL/M9wFFmMZAgFDuL2YOnanFH4OI4iFzUqyh3XOL7nAGbSlSMZdzKMIyyTpNSbqZsWG9odwLeKvA==} resolution: {integrity: sha512-RJKZ9+vEBMeiPAvKNWyZjuYyUqMndcP1f335oHqn3BEQbs2NFtVrnK5+6Xg5wSM9TknNNpWghGDUCKGYF+xWXw==}
emoji-regex@10.3.0: emoji-regex@10.3.0:
resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==}
@@ -2952,9 +2952,6 @@ packages:
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
known-css-properties@0.29.0:
resolution: {integrity: sha512-Ne7wqW7/9Cz54PDt4I3tcV+hAyat8ypyOGzYRJQfdxnnjeWsTxt1cy8pjvvKeI5kfXuyvULyeeAvwvvtAX3ayQ==}
known-css-properties@0.30.0: known-css-properties@0.30.0:
resolution: {integrity: sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ==} resolution: {integrity: sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ==}
@@ -3622,8 +3619,8 @@ packages:
react: '>= 16.8.0 || 18.0.0' react: '>= 16.8.0 || 18.0.0'
react-dom: '>= 16.8.0 || 18.0.0' react-dom: '>= 16.8.0 || 18.0.0'
react-hook-form@7.51.3: react-hook-form@7.51.4:
resolution: {integrity: sha512-cvJ/wbHdhYx8aviSWh28w9ImjmVsb5Y05n1+FW786vEZQJV5STNM0pW6ujS+oiBecb0ARBxJFyAnXj9+GHXACQ==} resolution: {integrity: sha512-V14i8SEkh+V1gs6YtD0hdHYnoL4tp/HX/A45wWQN15CYr9bFRmmRdYStSO5L65lCCZRF+kYiSKhm9alqbcdiVA==}
engines: {node: '>=12.22.0'} engines: {node: '>=12.22.0'}
peerDependencies: peerDependencies:
react: ^16.8.0 || ^17 || ^18 react: ^16.8.0 || ^17 || ^18
@@ -3999,8 +3996,8 @@ packages:
peerDependencies: peerDependencies:
stylelint: ^14.0.0 || ^15.0.0 || ^16.0.1 stylelint: ^14.0.0 || ^15.0.0 || ^16.0.1
stylelint-scss@6.2.1: stylelint-scss@6.3.0:
resolution: {integrity: sha512-ZoGLbVb1keZYRVGQlhB8G6sZOoNqw61whzzzGFWp05N12ErqLFfBv3JPrXiMLZaW98sBS7K/vUQhRnvUj4vwdw==} resolution: {integrity: sha512-8OSpiuf1xC7f8kllJsBOFAOYp/mR/C1FXMVeOFjtJPw+AFvEmC93FaklHt7MlOqU4poxuQ1TkYMyfI0V+1SxjA==}
engines: {node: '>=18.12.0'} engines: {node: '>=18.12.0'}
peerDependencies: peerDependencies:
stylelint: ^16.0.2 stylelint: ^16.0.2
@@ -4218,8 +4215,8 @@ packages:
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
engines: {node: '>= 10.0.0'} engines: {node: '>= 10.0.0'}
update-browserslist-db@1.0.14: update-browserslist-db@1.0.15:
resolution: {integrity: sha512-JixKH8GR2pWYshIPUg/NujK3JO7JiqEEUiNArE86NQyrgUuZeTlZQN3xuS/yiV5Kb48ev9K6RqNkaJjXsdg7Jw==} resolution: {integrity: sha512-K9HWH62x3/EalU1U6sjSZiylm9C8tgq2mSvshZpqc7QE69RaA2qjhkW2HlNA0tFpEbtyFz7HTqbSdN4MSwUodA==}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
browserslist: '>= 4.21.0' browserslist: '>= 4.21.0'
@@ -5829,9 +5826,9 @@ snapshots:
browserslist@4.23.0: browserslist@4.23.0:
dependencies: dependencies:
caniuse-lite: 1.0.30001615 caniuse-lite: 1.0.30001615
electron-to-chromium: 1.4.754 electron-to-chromium: 1.4.756
node-releases: 2.0.14 node-releases: 2.0.14
update-browserslist-db: 1.0.14(browserslist@4.23.0) update-browserslist-db: 1.0.15(browserslist@4.23.0)
buffer-alloc-unsafe@1.1.0: {} buffer-alloc-unsafe@1.1.0: {}
@@ -6150,7 +6147,7 @@ snapshots:
eastasianwidth@0.2.0: {} eastasianwidth@0.2.0: {}
electron-to-chromium@1.4.754: {} electron-to-chromium@1.4.756: {}
emoji-regex@10.3.0: {} emoji-regex@10.3.0: {}
@@ -7100,8 +7097,6 @@ snapshots:
kind-of@6.0.3: {} kind-of@6.0.3: {}
known-css-properties@0.29.0: {}
known-css-properties@0.30.0: {} known-css-properties@0.30.0: {}
less@4.2.0: less@4.2.0:
@@ -7854,7 +7849,7 @@ snapshots:
react: 18.3.1 react: 18.3.1
react-dom: 18.3.1(react@18.3.1) react-dom: 18.3.1(react@18.3.1)
react-hook-form@7.51.3(react@18.3.1): react-hook-form@7.51.4(react@18.3.1):
dependencies: dependencies:
react: 18.3.1 react: 18.3.1
@@ -8269,9 +8264,9 @@ snapshots:
postcss-sorting: 8.0.2(postcss@8.4.38) postcss-sorting: 8.0.2(postcss@8.4.38)
stylelint: 16.5.0(typescript@5.4.5) stylelint: 16.5.0(typescript@5.4.5)
stylelint-scss@6.2.1(stylelint@16.5.0(typescript@5.4.5)): stylelint-scss@6.3.0(stylelint@16.5.0(typescript@5.4.5)):
dependencies: dependencies:
known-css-properties: 0.29.0 known-css-properties: 0.30.0
postcss-media-query-parser: 0.2.3 postcss-media-query-parser: 0.2.3
postcss-resolve-nested-selector: 0.1.1 postcss-resolve-nested-selector: 0.1.1
postcss-selector-parser: 6.0.16 postcss-selector-parser: 6.0.16
@@ -8606,7 +8601,7 @@ snapshots:
universalify@2.0.1: {} universalify@2.0.1: {}
update-browserslist-db@1.0.14(browserslist@4.23.0): update-browserslist-db@1.0.15(browserslist@4.23.0):
dependencies: dependencies:
browserslist: 4.23.0 browserslist: 4.23.0
escalade: 3.1.2 escalade: 3.1.2

View File

@@ -1,6 +1,6 @@
function main(params) { function main(config) {
if (params.mode === "script") { if (config.mode === "script") {
params.mode = "rule"; config.mode = "rule";
} }
return params; return config;
} }

View File

@@ -1,10 +1,10 @@
function main(params) { function main(config) {
if (Array.isArray(params.proxies)) { if (Array.isArray(config.proxies)) {
params.proxies.forEach((p, i) => { config.proxies.forEach((p, i) => {
if (p.type === "hysteria" && typeof p.alpn === "string") { if (p.type === "hysteria" && typeof p.alpn === "string") {
params.proxies[i].alpn = [p.alpn]; config.proxies[i].alpn = [p.alpn];
} }
}); });
} }
return params; return config;
} }

View File

@@ -1,18 +1,17 @@
//! Some config file template //! Some config file template
/// template for new a profile item /// template for new a profile item
pub const ITEM_LOCAL: &str = "# Profile Template for clash verge pub const ITEM_LOCAL: &str = "# Profile Template for Clash Verge
proxies: proxies: []
proxy-groups: proxy-groups: []
rules: rules: []
"; ";
/// enhanced profile /// enhanced profile
pub const ITEM_MERGE: &str = "# Merge Template for clash verge pub const ITEM_MERGE: &str = "# Profile Enhancement Merge Template for Clash Verge
# The `Merge` format used to enhance profile
prepend-rules: [] prepend-rules: []
@@ -36,9 +35,9 @@ append-proxy-groups: []
"; ";
/// enhanced profile /// enhanced profile
pub const ITEM_SCRIPT: &str = "// Define the `main` function pub const ITEM_SCRIPT: &str = "// Define main function (script entry)
function main(params) { function main(config) {
return params; return config;
} }
"; ";

View File

@@ -13,6 +13,7 @@ import {
import { useClash } from "@/hooks/use-clash"; import { useClash } from "@/hooks/use-clash";
import { BaseDialog, DialogRef, Notice, Switch } from "@/components/base"; import { BaseDialog, DialogRef, Notice, Switch } from "@/components/base";
import { StackModeSwitch } from "./stack-mode-switch"; import { StackModeSwitch } from "./stack-mode-switch";
import { enhanceProfiles } from "@/services/cmds";
export const TunViewer = forwardRef<DialogRef>((props, ref) => { export const TunViewer = forwardRef<DialogRef>((props, ref) => {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -65,6 +66,12 @@ export const TunViewer = forwardRef<DialogRef>((props, ref) => {
}), }),
false false
); );
try {
await enhanceProfiles();
Notice.success("Refresh clash config", 1000);
} catch (err: any) {
Notice.error(err.message || err.toString(), 3000);
}
setOpen(false); setOpen(false);
} catch (err: any) { } catch (err: any) {
Notice.error(err.message || err.toString()); Notice.error(err.message || err.toString());

View File

@@ -1,2 +1,2 @@
LINUX_VERSION-5.10 = .215 LINUX_VERSION-5.10 = .216
LINUX_KERNEL_HASH-5.10.215 = 879ca159c34ea9d3a6775f292cc59c2d3931d57dca00f0bebe2675ea0c82c6a9 LINUX_KERNEL_HASH-5.10.216 = e310588c4b23f0959614e60f007afc20e9b1a8f296d682b041fa129f96fbe151

View File

@@ -1,2 +1,2 @@
LINUX_VERSION-5.15 = .157 LINUX_VERSION-5.15 = .158
LINUX_KERNEL_HASH-5.15.157 = aff22351d34d69a16762dcf1fd51fe228da55d4b96b67247bdd598a86cc7a414 LINUX_KERNEL_HASH-5.15.158 = f9071c83a4fd8b80af026b48cfc1869bfa25883f9148b92b5dc1e1e1e26dd5c6

View File

@@ -1,2 +1,2 @@
LINUX_VERSION-5.4 = .274 LINUX_VERSION-5.4 = .275
LINUX_KERNEL_HASH-5.4.274 = eac7b421a43cd46a3dbebf7c85d075faa7e164d80d215d31fcd35544b6f79ed4 LINUX_KERNEL_HASH-5.4.275 = dad2b068946f0ca0026130d7ab17601d5074d90b381379c4479314d4edf4304c

View File

@@ -19,7 +19,7 @@ Subject: [PATCH 210/210] b44: register adm switch
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <asm/io.h> #include <asm/io.h>
@@ -2249,6 +2251,69 @@ static void b44_adjust_link(struct net_d @@ -2251,6 +2253,69 @@ static void b44_adjust_link(struct net_d
} }
} }
@@ -89,7 +89,7 @@ Subject: [PATCH 210/210] b44: register adm switch
static int b44_register_phy_one(struct b44 *bp) static int b44_register_phy_one(struct b44 *bp)
{ {
__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
@@ -2285,6 +2350,9 @@ static int b44_register_phy_one(struct b @@ -2287,6 +2352,9 @@ static int b44_register_phy_one(struct b
if (!mdiobus_is_registered_device(bp->mii_bus, bp->phy_addr) && if (!mdiobus_is_registered_device(bp->mii_bus, bp->phy_addr) &&
(sprom->boardflags_lo & (B44_BOARDFLAG_ROBO | B44_BOARDFLAG_ADM))) { (sprom->boardflags_lo & (B44_BOARDFLAG_ROBO | B44_BOARDFLAG_ADM))) {
@@ -99,7 +99,7 @@ Subject: [PATCH 210/210] b44: register adm switch
dev_info(sdev->dev, dev_info(sdev->dev,
"could not find PHY at %i, use fixed one\n", "could not find PHY at %i, use fixed one\n",
bp->phy_addr); bp->phy_addr);
@@ -2481,6 +2549,7 @@ static void b44_remove_one(struct ssb_de @@ -2483,6 +2551,7 @@ static void b44_remove_one(struct ssb_de
unregister_netdev(dev); unregister_netdev(dev);
if (bp->flags & B44_FLAG_EXTERNAL_PHY) if (bp->flags & B44_FLAG_EXTERNAL_PHY)
b44_unregister_phy_one(bp); b44_unregister_phy_one(bp);

View File

@@ -43,7 +43,7 @@
if (bp->flags & B44_FLAG_EXTERNAL_PHY) if (bp->flags & B44_FLAG_EXTERNAL_PHY)
return 0; return 0;
@@ -2179,6 +2204,8 @@ static int b44_get_invariants(struct b44 @@ -2181,6 +2206,8 @@ static int b44_get_invariants(struct b44
* valid PHY address. */ * valid PHY address. */
bp->phy_addr &= 0x1F; bp->phy_addr &= 0x1F;

View File

@@ -1913,7 +1913,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
eth_hw_addr_inherit(slave_dev, master); eth_hw_addr_inherit(slave_dev, master);
--- a/net/ethernet/eth.c --- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c +++ b/net/ethernet/eth.c
@@ -506,13 +506,14 @@ unsigned char * __weak arch_get_platform @@ -496,13 +496,14 @@ unsigned char * __weak arch_get_platform
int eth_platform_get_mac_address(struct device *dev, u8 *mac_addr) int eth_platform_get_mac_address(struct device *dev, u8 *mac_addr)
{ {

View File

@@ -35,7 +35,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
/* Enable checksum offload */ /* Enable checksum offload */
*tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP |
@@ -1587,17 +1588,19 @@ ax88179_tx_fixup(struct usbnet *dev, str @@ -1582,17 +1583,19 @@ ax88179_tx_fixup(struct usbnet *dev, str
{ {
u32 tx_hdr1, tx_hdr2; u32 tx_hdr1, tx_hdr2;
int frame_size = dev->maxpacket; int frame_size = dev->maxpacket;
@@ -57,7 +57,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
if ((skb_header_cloned(skb) || headroom < 0) && if ((skb_header_cloned(skb) || headroom < 0) &&
pskb_expand_head(skb, headroom < 0 ? 8 : 0, 0, GFP_ATOMIC)) { pskb_expand_head(skb, headroom < 0 ? 8 : 0, 0, GFP_ATOMIC)) {
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
@@ -1608,6 +1611,8 @@ ax88179_tx_fixup(struct usbnet *dev, str @@ -1603,6 +1606,8 @@ ax88179_tx_fixup(struct usbnet *dev, str
put_unaligned_le32(tx_hdr1, ptr); put_unaligned_le32(tx_hdr1, ptr);
put_unaligned_le32(tx_hdr2, ptr + 4); put_unaligned_le32(tx_hdr2, ptr + 4);

View File

@@ -73,7 +73,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
--- a/arch/Kconfig --- a/arch/Kconfig
+++ b/arch/Kconfig +++ b/arch/Kconfig
@@ -1299,6 +1299,14 @@ config ARCH_HAS_ELFCORE_COMPAT @@ -1307,6 +1307,14 @@ config ARCH_HAS_ELFCORE_COMPAT
config ARCH_HAS_PARANOID_L1D_FLUSH config ARCH_HAS_PARANOID_L1D_FLUSH
bool bool
@@ -90,7 +90,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
source "scripts/gcc-plugins/Kconfig" source "scripts/gcc-plugins/Kconfig"
--- a/arch/x86/Kconfig --- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig +++ b/arch/x86/Kconfig
@@ -85,6 +85,7 @@ config X86 @@ -86,6 +86,7 @@ config X86
select ARCH_HAS_PMEM_API if X86_64 select ARCH_HAS_PMEM_API if X86_64
select ARCH_HAS_PTE_DEVMAP if X86_64 select ARCH_HAS_PTE_DEVMAP if X86_64
select ARCH_HAS_PTE_SPECIAL select ARCH_HAS_PTE_SPECIAL

View File

@@ -552,7 +552,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
--- a/kernel/bounds.c --- a/kernel/bounds.c
+++ b/kernel/bounds.c +++ b/kernel/bounds.c
@@ -22,6 +22,11 @@ int main(void) @@ -22,6 +22,11 @@ int main(void)
DEFINE(NR_CPUS_BITS, bits_per(CONFIG_NR_CPUS)); DEFINE(NR_CPUS_BITS, order_base_2(CONFIG_NR_CPUS));
#endif #endif
DEFINE(SPINLOCK_SIZE, sizeof(spinlock_t)); DEFINE(SPINLOCK_SIZE, sizeof(spinlock_t));
+#ifdef CONFIG_LRU_GEN +#ifdef CONFIG_LRU_GEN

View File

@@ -1,30 +0,0 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Mon, 7 Feb 2022 10:27:22 +0100
Subject: [PATCH] arm64: dts: mediatek: mt7622: add support for coherent
DMA
It improves performance by eliminating the need for a cache flush on rx and tx
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
@@ -357,7 +357,7 @@
};
cci_control2: slave-if@5000 {
- compatible = "arm,cci-400-ctrl-if";
+ compatible = "arm,cci-400-ctrl-if", "syscon";
interface-type = "ace";
reg = <0x5000 0x1000>;
};
@@ -938,6 +938,8 @@
power-domains = <&scpsys MT7622_POWER_DOMAIN_ETHSYS>;
mediatek,ethsys = <&ethsys>;
mediatek,sgmiisys = <&sgmiisys>;
+ mediatek,cci-control = <&cci_control2>;
+ dma-coherent;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";

View File

@@ -1,62 +0,0 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Sat, 5 Feb 2022 18:36:36 +0100
Subject: [PATCH] arm64: dts: mediatek: mt7622: introduce nodes for
Wireless Ethernet Dispatch
Introduce wed0 and wed1 nodes in order to enable offloading forwarding
between ethernet and wireless devices on the mt7622 chipset.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
@@ -894,6 +894,11 @@
};
};
+ hifsys: syscon@1af00000 {
+ compatible = "mediatek,mt7622-hifsys", "syscon";
+ reg = <0 0x1af00000 0 0x70>;
+ };
+
ethsys: syscon@1b000000 {
compatible = "mediatek,mt7622-ethsys",
"syscon";
@@ -912,6 +917,26 @@
#dma-cells = <1>;
};
+ pcie_mirror: pcie-mirror@10000400 {
+ compatible = "mediatek,mt7622-pcie-mirror",
+ "syscon";
+ reg = <0 0x10000400 0 0x10>;
+ };
+
+ wed0: wed@1020a000 {
+ compatible = "mediatek,mt7622-wed",
+ "syscon";
+ reg = <0 0x1020a000 0 0x1000>;
+ interrupts = <GIC_SPI 214 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ wed1: wed@1020b000 {
+ compatible = "mediatek,mt7622-wed",
+ "syscon";
+ reg = <0 0x1020b000 0 0x1000>;
+ interrupts = <GIC_SPI 215 IRQ_TYPE_LEVEL_LOW>;
+ };
+
eth: ethernet@1b100000 {
compatible = "mediatek,mt7622-eth",
"mediatek,mt2701-eth",
@@ -939,6 +964,9 @@
mediatek,ethsys = <&ethsys>;
mediatek,sgmiisys = <&sgmiisys>;
mediatek,cci-control = <&cci_control2>;
+ mediatek,wed = <&wed0>, <&wed1>;
+ mediatek,pcie-mirror = <&pcie_mirror>;
+ mediatek,hifsys = <&hifsys>;
dma-coherent;
#address-cells = <1>;
#size-cells = <0>;

View File

@@ -13,7 +13,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi --- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
@@ -963,7 +963,7 @@ @@ -957,7 +957,7 @@
power-domains = <&scpsys MT7622_POWER_DOMAIN_ETHSYS>; power-domains = <&scpsys MT7622_POWER_DOMAIN_ETHSYS>;
mediatek,ethsys = <&ethsys>; mediatek,ethsys = <&ethsys>;
mediatek,sgmiisys = <&sgmiisys>; mediatek,sgmiisys = <&sgmiisys>;

View File

@@ -35,7 +35,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
ax88179_reset(dev); ax88179_reset(dev);
@@ -1507,17 +1508,19 @@ ax88179_tx_fixup(struct usbnet *dev, str @@ -1502,17 +1503,19 @@ ax88179_tx_fixup(struct usbnet *dev, str
{ {
u32 tx_hdr1, tx_hdr2; u32 tx_hdr1, tx_hdr2;
int frame_size = dev->maxpacket; int frame_size = dev->maxpacket;
@@ -57,7 +57,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
if ((skb_header_cloned(skb) || headroom < 0) && if ((skb_header_cloned(skb) || headroom < 0) &&
pskb_expand_head(skb, headroom < 0 ? 8 : 0, 0, GFP_ATOMIC)) { pskb_expand_head(skb, headroom < 0 ? 8 : 0, 0, GFP_ATOMIC)) {
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
@@ -1528,6 +1531,8 @@ ax88179_tx_fixup(struct usbnet *dev, str @@ -1523,6 +1526,8 @@ ax88179_tx_fixup(struct usbnet *dev, str
put_unaligned_le32(tx_hdr1, ptr); put_unaligned_le32(tx_hdr1, ptr);
put_unaligned_le32(tx_hdr2, ptr + 4); put_unaligned_le32(tx_hdr2, ptr + 4);

View File

@@ -17,7 +17,7 @@ Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
--- a/drivers/bluetooth/btusb.c --- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c
@@ -2287,6 +2287,23 @@ struct btmtk_section_map { @@ -2289,6 +2289,23 @@ struct btmtk_section_map {
}; };
} __packed; } __packed;
@@ -41,7 +41,7 @@ Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
static void btusb_mtk_wmt_recv(struct urb *urb) static void btusb_mtk_wmt_recv(struct urb *urb)
{ {
struct hci_dev *hdev = urb->context; struct hci_dev *hdev = urb->context;
@@ -3941,6 +3958,7 @@ static int btusb_probe(struct usb_interf @@ -3943,6 +3960,7 @@ static int btusb_probe(struct usb_interf
hdev->shutdown = btusb_mtk_shutdown; hdev->shutdown = btusb_mtk_shutdown;
hdev->manufacturer = 70; hdev->manufacturer = 70;
hdev->cmd_timeout = btusb_mtk_cmd_timeout; hdev->cmd_timeout = btusb_mtk_cmd_timeout;

View File

@@ -18,7 +18,7 @@ Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
--- a/drivers/bluetooth/btusb.c --- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c
@@ -2292,7 +2292,7 @@ static int btusb_set_bdaddr_mtk(struct h @@ -2294,7 +2294,7 @@ static int btusb_set_bdaddr_mtk(struct h
struct sk_buff *skb; struct sk_buff *skb;
long ret; long ret;

View File

@@ -58,7 +58,7 @@ Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
--- a/drivers/bluetooth/btusb.c --- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c
@@ -476,6 +476,9 @@ static const struct usb_device_id blackl @@ -478,6 +478,9 @@ static const struct usb_device_id blackl
{ USB_DEVICE(0x13d3, 0x3564), .driver_info = BTUSB_MEDIATEK | { USB_DEVICE(0x13d3, 0x3564), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH | BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES }, BTUSB_VALID_LE_STATES },

View File

@@ -56,7 +56,7 @@ Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
--- a/drivers/bluetooth/btusb.c --- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c
@@ -467,6 +467,9 @@ static const struct usb_device_id blackl @@ -469,6 +469,9 @@ static const struct usb_device_id blackl
BTUSB_VALID_LE_STATES }, BTUSB_VALID_LE_STATES },
/* Additional MediaTek MT7921 Bluetooth devices */ /* Additional MediaTek MT7921 Bluetooth devices */

View File

@@ -54,7 +54,7 @@ Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
--- a/drivers/bluetooth/btusb.c --- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c
@@ -485,6 +485,9 @@ static const struct usb_device_id blackl @@ -487,6 +487,9 @@ static const struct usb_device_id blackl
{ USB_DEVICE(0x0489, 0xe0cd), .driver_info = BTUSB_MEDIATEK | { USB_DEVICE(0x0489, 0xe0cd), .driver_info = BTUSB_MEDIATEK |
BTUSB_WIDEBAND_SPEECH | BTUSB_WIDEBAND_SPEECH |
BTUSB_VALID_LE_STATES }, BTUSB_VALID_LE_STATES },

View File

@@ -1775,7 +1775,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
eth_hw_addr_inherit(slave_dev, master); eth_hw_addr_inherit(slave_dev, master);
--- a/net/ethernet/eth.c --- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c +++ b/net/ethernet/eth.c
@@ -550,13 +550,14 @@ unsigned char * __weak arch_get_platform @@ -540,13 +540,14 @@ unsigned char * __weak arch_get_platform
int eth_platform_get_mac_address(struct device *dev, u8 *mac_addr) int eth_platform_get_mac_address(struct device *dev, u8 *mac_addr)
{ {

View File

@@ -11,7 +11,7 @@ Submitted-by: Yousong Zhou <yszhou4tech@gmail.com>
--- a/net/ethernet/eth.c --- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c +++ b/net/ethernet/eth.c
@@ -538,6 +538,63 @@ int eth_platform_get_mac_address(struct @@ -528,6 +528,63 @@ int eth_platform_get_mac_address(struct
} }
EXPORT_SYMBOL(eth_platform_get_mac_address); EXPORT_SYMBOL(eth_platform_get_mac_address);
@@ -75,7 +75,7 @@ Submitted-by: Yousong Zhou <yszhou4tech@gmail.com>
/** /**
* nvmem_get_mac_address - Obtain the MAC address from an nvmem cell named * nvmem_get_mac_address - Obtain the MAC address from an nvmem cell named
* 'mac-address' associated with given device. * 'mac-address' associated with given device.
@@ -551,19 +608,23 @@ int nvmem_get_mac_address(struct device @@ -541,19 +598,23 @@ int nvmem_get_mac_address(struct device
{ {
struct nvmem_cell *cell; struct nvmem_cell *cell;
const void *mac; const void *mac;

View File

@@ -1,6 +1,6 @@
--- a/drivers/usb/serial/option.c --- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c
@@ -278,6 +278,7 @@ static void option_instat_callback(struc @@ -282,6 +282,7 @@ static void option_instat_callback(struc
#define QUECTEL_PRODUCT_EM061K_LWW 0x6008 #define QUECTEL_PRODUCT_EM061K_LWW 0x6008
#define QUECTEL_PRODUCT_EM061K_LCN 0x6009 #define QUECTEL_PRODUCT_EM061K_LCN 0x6009
#define QUECTEL_PRODUCT_EC200T 0x6026 #define QUECTEL_PRODUCT_EC200T 0x6026
@@ -8,7 +8,7 @@
#define QUECTEL_PRODUCT_RM500K 0x7001 #define QUECTEL_PRODUCT_RM500K 0x7001
#define CMOTECH_VENDOR_ID 0x16d8 #define CMOTECH_VENDOR_ID 0x16d8
@@ -1251,6 +1252,7 @@ static const struct usb_device_id option @@ -1267,6 +1268,7 @@ static const struct usb_device_id option
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200U, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200U, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200S_CN, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200S_CN, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200T, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200T, 0xff, 0, 0) },

View File

@@ -91,7 +91,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
for (i = sizeof(struct ipt_entry); for (i = sizeof(struct ipt_entry);
i < e->target_offset; i < e->target_offset;
i += m->u.match_size) { i += m->u.match_size) {
@@ -1224,12 +1261,15 @@ compat_copy_entry_to_user(struct ipt_ent @@ -1226,12 +1263,15 @@ compat_copy_entry_to_user(struct ipt_ent
compat_uint_t origsize; compat_uint_t origsize;
const struct xt_entry_match *ematch; const struct xt_entry_match *ematch;
int ret = 0; int ret = 0;

View File

@@ -136,9 +136,9 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
/** /**
* eth_type_trans - determine the packet's protocol ID. * eth_type_trans - determine the packet's protocol ID.
* @skb: received socket data * @skb: received socket data
@@ -174,6 +186,10 @@ __be16 eth_type_trans(struct sk_buff *sk @@ -426,6 +438,10 @@ struct sk_buff *eth_gro_receive(struct l
} else { NAPI_GRO_CB(p)->same_flow = 0;
skb->pkt_type = PACKET_OTHERHOST; continue;
} }
+ +
+ if (eth_check_local_mask(eth->h_dest, dev->dev_addr, + if (eth_check_local_mask(eth->h_dest, dev->dev_addr,
@@ -146,4 +146,4 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+ skb->gro_skip = 1; + skb->gro_skip = 1;
} }
/* type = eh->h_proto;

View File

@@ -1,30 +0,0 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Mon, 7 Feb 2022 10:27:22 +0100
Subject: [PATCH] arm64: dts: mediatek: mt7622: add support for coherent
DMA
It improves performance by eliminating the need for a cache flush on rx and tx
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
@@ -357,7 +357,7 @@
};
cci_control2: slave-if@5000 {
- compatible = "arm,cci-400-ctrl-if";
+ compatible = "arm,cci-400-ctrl-if", "syscon";
interface-type = "ace";
reg = <0x5000 0x1000>;
};
@@ -937,6 +937,8 @@
power-domains = <&scpsys MT7622_POWER_DOMAIN_ETHSYS>;
mediatek,ethsys = <&ethsys>;
mediatek,sgmiisys = <&sgmiisys>;
+ mediatek,cci-control = <&cci_control2>;
+ dma-coherent;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";

View File

@@ -1,62 +0,0 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Sat, 5 Feb 2022 18:36:36 +0100
Subject: [PATCH] arm64: dts: mediatek: mt7622: introduce nodes for
Wireless Ethernet Dispatch
Introduce wed0 and wed1 nodes in order to enable offloading forwarding
between ethernet and wireless devices on the mt7622 chipset.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
@@ -893,6 +893,11 @@
};
};
+ hifsys: syscon@1af00000 {
+ compatible = "mediatek,mt7622-hifsys", "syscon";
+ reg = <0 0x1af00000 0 0x70>;
+ };
+
ethsys: syscon@1b000000 {
compatible = "mediatek,mt7622-ethsys",
"syscon";
@@ -911,6 +916,26 @@
#dma-cells = <1>;
};
+ pcie_mirror: pcie-mirror@10000400 {
+ compatible = "mediatek,mt7622-pcie-mirror",
+ "syscon";
+ reg = <0 0x10000400 0 0x10>;
+ };
+
+ wed0: wed@1020a000 {
+ compatible = "mediatek,mt7622-wed",
+ "syscon";
+ reg = <0 0x1020a000 0 0x1000>;
+ interrupts = <GIC_SPI 214 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ wed1: wed@1020b000 {
+ compatible = "mediatek,mt7622-wed",
+ "syscon";
+ reg = <0 0x1020b000 0 0x1000>;
+ interrupts = <GIC_SPI 215 IRQ_TYPE_LEVEL_LOW>;
+ };
+
eth: ethernet@1b100000 {
compatible = "mediatek,mt7622-eth",
"mediatek,mt2701-eth",
@@ -938,6 +963,9 @@
mediatek,ethsys = <&ethsys>;
mediatek,sgmiisys = <&sgmiisys>;
mediatek,cci-control = <&cci_control2>;
+ mediatek,wed = <&wed0>, <&wed1>;
+ mediatek,pcie-mirror = <&pcie_mirror>;
+ mediatek,hifsys = <&hifsys>;
dma-coherent;
#address-cells = <1>;
#size-cells = <0>;

View File

@@ -61,7 +61,7 @@ Signed-off-by: Imre Kaloz <kaloz@openwrt.org>
/* /*
* We need to store the untouched command line for future reference. * We need to store the untouched command line for future reference.
* We also need to store the touched command line since the parameter * We also need to store the touched command line since the parameter
@@ -866,6 +889,7 @@ asmlinkage __visible void __init __no_sa @@ -868,6 +891,7 @@ asmlinkage __visible void __init __no_sa
pr_notice("%s", linux_banner); pr_notice("%s", linux_banner);
early_security_init(); early_security_init();
setup_arch(&command_line); setup_arch(&command_line);

View File

@@ -136,9 +136,9 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
/** /**
* eth_type_trans - determine the packet's protocol ID. * eth_type_trans - determine the packet's protocol ID.
* @skb: received socket data * @skb: received socket data
@@ -173,6 +185,10 @@ __be16 eth_type_trans(struct sk_buff *sk @@ -421,6 +433,10 @@ struct sk_buff *eth_gro_receive(struct l
} else { NAPI_GRO_CB(p)->same_flow = 0;
skb->pkt_type = PACKET_OTHERHOST; continue;
} }
+ +
+ if (eth_check_local_mask(eth->h_dest, dev->dev_addr, + if (eth_check_local_mask(eth->h_dest, dev->dev_addr,
@@ -146,4 +146,4 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+ skb->gro_skip = 1; + skb->gro_skip = 1;
} }
/* type = eh->h_proto;

View File

@@ -1,8 +1,8 @@
--- a/drivers/net/usb/qmi_wwan.c --- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c
@@ -1431,6 +1431,9 @@ static const struct usb_device_id produc @@ -1420,6 +1420,9 @@ static const struct usb_device_id produc
{QMI_FIXED_INTF(0x0489, 0xe0b5, 0)}, /* Foxconn T77W968 LTE with eSIM support*/
{QMI_FIXED_INTF(0x2692, 0x9025, 4)}, /* Cellient MPL200 (rebranded Qualcomm 05c6:9025) */ {QMI_FIXED_INTF(0x2692, 0x9025, 4)}, /* Cellient MPL200 (rebranded Qualcomm 05c6:9025) */
{QMI_QUIRK_SET_DTR(0x1546, 0x1312, 4)}, /* u-blox LARA-R6 01B */
{QMI_QUIRK_SET_DTR(0x1546, 0x1342, 4)}, /* u-blox LARA-L6 */ {QMI_QUIRK_SET_DTR(0x1546, 0x1342, 4)}, /* u-blox LARA-L6 */
+ {QMI_FIXED_INTF(0x2077, 0x2002, 4)}, /* T&W TW04C */ + {QMI_FIXED_INTF(0x2077, 0x2002, 4)}, /* T&W TW04C */
+ {QMI_FIXED_INTF(0x2077, 0x2003, 4)}, /* T&W TW12G */ + {QMI_FIXED_INTF(0x2077, 0x2003, 4)}, /* T&W TW12G */

View File

@@ -506,7 +506,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+MODULE_ALIAS("nf-flow-table-hw"); +MODULE_ALIAS("nf-flow-table-hw");
--- a/net/netfilter/nf_tables_api.c --- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c
@@ -6041,6 +6041,13 @@ static int nf_tables_flowtable_parse_hoo @@ -6045,6 +6045,13 @@ static int nf_tables_flowtable_parse_hoo
if (err < 0) if (err < 0)
return err; return err;
@@ -520,7 +520,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
ops = kcalloc(n, sizeof(struct nf_hook_ops), GFP_KERNEL); ops = kcalloc(n, sizeof(struct nf_hook_ops), GFP_KERNEL);
if (!ops) if (!ops)
return -ENOMEM; return -ENOMEM;
@@ -6190,10 +6197,19 @@ static int nf_tables_newflowtable(struct @@ -6194,10 +6201,19 @@ static int nf_tables_newflowtable(struct
} }
flowtable->data.type = type; flowtable->data.type = type;
@@ -540,7 +540,7 @@ Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
err = nf_tables_flowtable_parse_hook(&ctx, nla[NFTA_FLOWTABLE_HOOK], err = nf_tables_flowtable_parse_hook(&ctx, nla[NFTA_FLOWTABLE_HOOK],
flowtable); flowtable);
if (err < 0) if (err < 0)
@@ -6319,7 +6335,8 @@ static int nf_tables_fill_flowtable_info @@ -6323,7 +6339,8 @@ static int nf_tables_fill_flowtable_info
nla_put_string(skb, NFTA_FLOWTABLE_NAME, flowtable->name) || nla_put_string(skb, NFTA_FLOWTABLE_NAME, flowtable->name) ||
nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use)) || nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use)) ||
nla_put_be64(skb, NFTA_FLOWTABLE_HANDLE, cpu_to_be64(flowtable->handle), nla_put_be64(skb, NFTA_FLOWTABLE_HANDLE, cpu_to_be64(flowtable->handle),

View File

@@ -136,9 +136,9 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
/** /**
* eth_type_trans - determine the packet's protocol ID. * eth_type_trans - determine the packet's protocol ID.
* @skb: received socket data * @skb: received socket data
@@ -174,6 +186,10 @@ __be16 eth_type_trans(struct sk_buff *sk @@ -470,6 +482,10 @@ struct sk_buff *eth_gro_receive(struct l
} else { NAPI_GRO_CB(p)->same_flow = 0;
skb->pkt_type = PACKET_OTHERHOST; continue;
} }
+ +
+ if (eth_check_local_mask(eth->h_dest, dev->dev_addr, + if (eth_check_local_mask(eth->h_dest, dev->dev_addr,
@@ -146,4 +146,4 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+ skb->gro_skip = 1; + skb->gro_skip = 1;
} }
/* type = eh->h_proto;

View File

@@ -189,7 +189,7 @@ Signed-off-by: Adrian Panella <ianchi74@outlook.com>
static int kernel_init(void *); static int kernel_init(void *);
extern void init_IRQ(void); extern void init_IRQ(void);
@@ -903,6 +907,18 @@ asmlinkage __visible void __init __no_sa @@ -905,6 +909,18 @@ asmlinkage __visible void __init __no_sa
pr_notice("Kernel command line: %s\n", saved_command_line); pr_notice("Kernel command line: %s\n", saved_command_line);
/* parameters may set static keys */ /* parameters may set static keys */
jump_label_init(); jump_label_init();

View File

@@ -1,6 +1,6 @@
--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi --- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
@@ -559,6 +559,7 @@ @@ -556,6 +556,7 @@
compatible = "mediatek,mt7622-nor", compatible = "mediatek,mt7622-nor",
"mediatek,mt8173-nor"; "mediatek,mt8173-nor";
reg = <0 0x11014000 0 0xe0>; reg = <0 0x11014000 0 0xe0>;

View File

@@ -14,7 +14,7 @@ Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi --- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
@@ -553,6 +553,18 @@ @@ -550,6 +550,18 @@
status = "disabled"; status = "disabled";
}; };

View File

@@ -95,7 +95,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi --- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
@@ -339,7 +339,7 @@ @@ -337,7 +337,7 @@
#interrupt-cells = <3>; #interrupt-cells = <3>;
interrupt-parent = <&gic>; interrupt-parent = <&gic>;
reg = <0 0x10310000 0 0x1000>, reg = <0 0x10310000 0 0x1000>,

View File

@@ -112,7 +112,7 @@ Signed-off-by: Rui Salvaterra <rsalvaterra@gmail.com>
--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi --- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
@@ -942,6 +942,7 @@ @@ -938,6 +938,7 @@
clock-names = "hsdma"; clock-names = "hsdma";
power-domains = <&scpsys MT7622_POWER_DOMAIN_ETHSYS>; power-domains = <&scpsys MT7622_POWER_DOMAIN_ETHSYS>;
#dma-cells = <1>; #dma-cells = <1>;

View File

@@ -21,7 +21,7 @@ Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com>
--- a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi --- a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
@@ -915,64 +915,67 @@ @@ -916,64 +916,67 @@
}; };
}; };
@@ -194,7 +194,7 @@ Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com>
&pio { &pio {
--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi --- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
@@ -809,75 +809,83 @@ @@ -804,75 +804,83 @@
#reset-cells = <1>; #reset-cells = <1>;
}; };

View File

@@ -1,6 +1,6 @@
--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi --- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
@@ -849,6 +849,12 @@ @@ -844,6 +844,12 @@
#address-cells = <0>; #address-cells = <0>;
#interrupt-cells = <1>; #interrupt-cells = <1>;
}; };
@@ -13,7 +13,7 @@
}; };
pcie1: pcie@1a145000 { pcie1: pcie@1a145000 {
@@ -887,6 +893,12 @@ @@ -882,6 +888,12 @@
#address-cells = <0>; #address-cells = <0>;
#interrupt-cells = <1>; #interrupt-cells = <1>;
}; };

View File

@@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi --- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
@@ -837,6 +837,9 @@ @@ -832,6 +832,9 @@
bus-range = <0x00 0xff>; bus-range = <0x00 0xff>;
ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x8000000>; ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x8000000>;
status = "disabled"; status = "disabled";
@@ -20,7 +20,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
#interrupt-cells = <1>; #interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 7>; interrupt-map-mask = <0 0 0 7>;
@@ -881,6 +884,9 @@ @@ -876,6 +879,9 @@
bus-range = <0x00 0xff>; bus-range = <0x00 0xff>;
ranges = <0x82000000 0 0x28000000 0x0 0x28000000 0 0x8000000>; ranges = <0x82000000 0 0x28000000 0x0 0x28000000 0 0x8000000>;
status = "disabled"; status = "disabled";

View File

@@ -187,7 +187,7 @@ Signed-off-by: Michael Gray <michael.gray@lantisproject.com>
static int kernel_init(void *); static int kernel_init(void *);
extern void init_IRQ(void); extern void init_IRQ(void);
@@ -901,6 +905,18 @@ asmlinkage __visible void __init __no_sa @@ -903,6 +907,18 @@ asmlinkage __visible void __init __no_sa
page_alloc_init(); page_alloc_init();
pr_notice("Kernel command line: %s\n", saved_command_line); pr_notice("Kernel command line: %s\n", saved_command_line);

View File

@@ -168,7 +168,7 @@ Signed-off-by: Adrian Panella <ianchi74@outlook.com>
static int kernel_init(void *); static int kernel_init(void *);
extern void init_IRQ(void); extern void init_IRQ(void);
@@ -901,6 +905,18 @@ asmlinkage __visible void __init __no_sa @@ -903,6 +907,18 @@ asmlinkage __visible void __init __no_sa
page_alloc_init(); page_alloc_init();
pr_notice("Kernel command line: %s\n", saved_command_line); pr_notice("Kernel command line: %s\n", saved_command_line);

View File

@@ -1849,7 +1849,7 @@
+obj-$(CONFIG_PHYTIUM_IXIC) += irq-phytium-ixic.o +obj-$(CONFIG_PHYTIUM_IXIC) += irq-phytium-ixic.o
--- a/drivers/irqchip/irq-gic-v3-its.c --- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -4792,6 +4792,7 @@ static void its_restore_enable(void) @@ -4787,6 +4787,7 @@ static void its_restore_enable(void)
{ {
struct its_node *its; struct its_node *its;
int ret; int ret;
@@ -1857,7 +1857,7 @@
raw_spin_lock(&its_lock); raw_spin_lock(&its_lock);
list_for_each_entry(its, &its_nodes, entry) { list_for_each_entry(its, &its_nodes, entry) {
@@ -4845,6 +4846,23 @@ static void its_restore_enable(void) @@ -4840,6 +4841,23 @@ static void its_restore_enable(void)
GITS_TYPER_HCC(gic_read_typer(base + GITS_TYPER))) GITS_TYPER_HCC(gic_read_typer(base + GITS_TYPER)))
its_cpu_init_collection(its); its_cpu_init_collection(its);
} }

View File

@@ -138,7 +138,7 @@ Subject: [PATCH] irqchip: gic-v3: add hackaround for rk3568 its
if (alloc_lpis) { if (alloc_lpis) {
lpi_map = its_lpi_alloc(nvecs, &lpi_base, &nr_lpis); lpi_map = its_lpi_alloc(nvecs, &lpi_base, &nr_lpis);
if (lpi_map) if (lpi_map)
@@ -4726,6 +4763,13 @@ static bool __maybe_unused its_enable_qu @@ -4721,6 +4758,13 @@ static bool __maybe_unused its_enable_qu
return true; return true;
} }
@@ -152,7 +152,7 @@ Subject: [PATCH] irqchip: gic-v3: add hackaround for rk3568 its
static const struct gic_quirk its_quirks[] = { static const struct gic_quirk its_quirks[] = {
#ifdef CONFIG_CAVIUM_ERRATUM_22375 #ifdef CONFIG_CAVIUM_ERRATUM_22375
{ {
@@ -4772,6 +4816,14 @@ static const struct gic_quirk its_quirks @@ -4767,6 +4811,14 @@ static const struct gic_quirk its_quirks
.init = its_enable_quirk_hip07_161600802, .init = its_enable_quirk_hip07_161600802,
}, },
#endif #endif
@@ -167,7 +167,7 @@ Subject: [PATCH] irqchip: gic-v3: add hackaround for rk3568 its
{ {
} }
}; };
@@ -4995,6 +5047,7 @@ static int __init its_probe_one(struct r @@ -4990,6 +5042,7 @@ static int __init its_probe_one(struct r
u64 baser, tmp, typer; u64 baser, tmp, typer;
struct page *page; struct page *page;
int err; int err;
@@ -175,7 +175,7 @@ Subject: [PATCH] irqchip: gic-v3: add hackaround for rk3568 its
its_base = ioremap(res->start, SZ_64K); its_base = ioremap(res->start, SZ_64K);
if (!its_base) { if (!its_base) {
@@ -5063,7 +5116,9 @@ static int __init its_probe_one(struct r @@ -5058,7 +5111,9 @@ static int __init its_probe_one(struct r
its->numa_node = numa_node; its->numa_node = numa_node;
@@ -186,7 +186,7 @@ Subject: [PATCH] irqchip: gic-v3: add hackaround for rk3568 its
get_order(ITS_CMD_QUEUE_SZ)); get_order(ITS_CMD_QUEUE_SZ));
if (!page) { if (!page) {
err = -ENOMEM; err = -ENOMEM;
@@ -5094,6 +5149,9 @@ static int __init its_probe_one(struct r @@ -5089,6 +5144,9 @@ static int __init its_probe_one(struct r
gits_write_cbaser(baser, its->base + GITS_CBASER); gits_write_cbaser(baser, its->base + GITS_CBASER);
tmp = gits_read_cbaser(its->base + GITS_CBASER); tmp = gits_read_cbaser(its->base + GITS_CBASER);

View File

@@ -98,4 +98,3 @@ API.
This software is released under the GPL-3.0 license. This software is released under the GPL-3.0 license.
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FMetaCubeX%2Fmihomo.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2FMetaCubeX%2Fmihomo?ref=badge_large)

View File

@@ -97,3 +97,7 @@ Options:
--ssl-key-log-file=<path> --ssl-key-log-file=<path>
Saves SSL keys for Wireshark inspection. Saves SSL keys for Wireshark inspection.
--no-post-quantum
Overrides the default and disables post-quantum key agreement.

View File

@@ -115,6 +115,6 @@ mkdir -p out
export DEPOT_TOOLS_WIN_TOOLCHAIN=0 export DEPOT_TOOLS_WIN_TOOLCHAIN=0
./gn/out/gn gen "$out" --args="$flags $EXTRA_FLAGS" --script-executable=$PYTHON ./gn/out/gn gen "$out" --args="$flags $EXTRA_FLAGS"
ninja -C "$out" naive ninja -C "$out" naive

View File

@@ -24,7 +24,11 @@ if [ ! "$target_cpu" ]; then
target_cpu="$host_cpu" target_cpu="$host_cpu"
fi fi
PYTHON=$(which python3 2>/dev/null || which python 2>/dev/null) if which python3 >/dev/null 2>/dev/null; then
PYTHON=python3
else
PYTHON=python
fi
# sysroot # sysroot
case "$target_os" in case "$target_os" in

View File

@@ -1744,6 +1744,12 @@ static_library("preload_decoder") {
executable("naive") { executable("naive") {
sources = [ sources = [
"tools/naive/http_proxy_server_socket.cc",
"tools/naive/http_proxy_server_socket.h",
"tools/naive/naive_command_line.cc",
"tools/naive/naive_command_line.h",
"tools/naive/naive_config.cc",
"tools/naive/naive_config.h",
"tools/naive/naive_connection.cc", "tools/naive/naive_connection.cc",
"tools/naive/naive_connection.h", "tools/naive/naive_connection.h",
"tools/naive/naive_padding_framer.cc", "tools/naive/naive_padding_framer.cc",
@@ -1752,15 +1758,13 @@ executable("naive") {
"tools/naive/naive_padding_socket.h", "tools/naive/naive_padding_socket.h",
"tools/naive/naive_protocol.cc", "tools/naive/naive_protocol.cc",
"tools/naive/naive_protocol.h", "tools/naive/naive_protocol.h",
"tools/naive/naive_proxy_bin.cc",
"tools/naive/naive_proxy_delegate.cc",
"tools/naive/naive_proxy_delegate.h",
"tools/naive/naive_proxy.cc", "tools/naive/naive_proxy.cc",
"tools/naive/naive_proxy.h", "tools/naive/naive_proxy.h",
"tools/naive/naive_proxy_bin.cc",
"tools/naive/naive_proxy_delegate.h",
"tools/naive/naive_proxy_delegate.cc",
"tools/naive/http_proxy_server_socket.cc",
"tools/naive/http_proxy_server_socket.h",
"tools/naive/redirect_resolver.h",
"tools/naive/redirect_resolver.cc", "tools/naive/redirect_resolver.cc",
"tools/naive/redirect_resolver.h",
"tools/naive/socks5_server_socket.cc", "tools/naive/socks5_server_socket.cc",
"tools/naive/socks5_server_socket.h", "tools/naive/socks5_server_socket.h",
] ]

View File

@@ -0,0 +1,74 @@
// Copyright 2024 klzgrad <kizdiv@gmail.com>. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/tools/naive/naive_command_line.h"
#include <memory>
#include <utility>
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#if BUILDFLAG(IS_WIN)
#include "base/strings/string_util_win.h"
#endif
DuplicateSwitchCollector::DuplicateSwitchCollector() = default;
DuplicateSwitchCollector::~DuplicateSwitchCollector() = default;
void DuplicateSwitchCollector::ResolveDuplicate(
std::string_view key,
base::CommandLine::StringPieceType new_value,
base::CommandLine::StringType& out_value) {
out_value = new_value;
values_by_key_[std::string(key)].push_back(
base::CommandLine::StringType(new_value));
}
const std::vector<base::CommandLine::StringType>&
DuplicateSwitchCollector::GetValuesByKey(std::string_view key) {
return values_by_key_[std::string(key)];
}
namespace {
DuplicateSwitchCollector* g_duplicate_switch_collector;
}
void DuplicateSwitchCollector::InitInstance() {
auto new_duplicate_switch_collector =
std::make_unique<DuplicateSwitchCollector>();
g_duplicate_switch_collector = new_duplicate_switch_collector.get();
base::CommandLine::SetDuplicateSwitchHandler(
std::move(new_duplicate_switch_collector));
}
DuplicateSwitchCollector& DuplicateSwitchCollector::GetInstance() {
CHECK(g_duplicate_switch_collector != nullptr);
return *g_duplicate_switch_collector;
}
base::Value::Dict GetSwitchesAsValue(const base::CommandLine& cmdline) {
base::Value::Dict dict;
for (const auto& [key, value] : cmdline.GetSwitches()) {
const std::vector<base::CommandLine::StringType>& values =
DuplicateSwitchCollector::GetInstance().GetValuesByKey(key);
if (values.size() > 1) {
base::Value::List list;
for (const base::CommandLine::StringType& v : values) {
#if BUILDFLAG(IS_WIN)
list.Append(base::AsStringPiece16(v));
#else
list.Append(v);
#endif
}
dict.Set(key, std::move(list));
} else {
#if BUILDFLAG(IS_WIN)
dict.Set(key, base::AsStringPiece16(value));
#else
dict.Set(key, value);
#endif
}
}
return dict;
}

View File

@@ -0,0 +1,36 @@
// Copyright 2024 klzgrad <kizdiv@gmail.com>. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_TOOLS_NAIVE_NAIVE_COMMAND_LINE_H_
#define NET_TOOLS_NAIVE_NAIVE_COMMAND_LINE_H_
#include <map>
#include <string>
#include <string_view>
#include <vector>
#include "base/command_line.h"
#include "base/values.h"
class DuplicateSwitchCollector : public base::DuplicateSwitchHandler {
public:
DuplicateSwitchCollector();
~DuplicateSwitchCollector() override;
void ResolveDuplicate(std::string_view key,
base::CommandLine::StringPieceType new_value,
base::CommandLine::StringType& out_value) override;
const std::vector<base::CommandLine::StringType>& GetValuesByKey(
std::string_view key);
static void InitInstance();
static DuplicateSwitchCollector& GetInstance();
private:
std::map<std::string, std::vector<base::CommandLine::StringType>>
values_by_key_;
};
base::Value::Dict GetSwitchesAsValue(const base::CommandLine& cmdline);
#endif // NET_TOOLS_NAIVE_NAIVE_COMMAND_LINE_H_

View File

@@ -0,0 +1,202 @@
// Copyright 2024 klzgrad <kizdiv@gmail.com>. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/tools/naive/naive_config.h"
#include <iostream>
#include "base/strings/escape.h"
#include "base/strings/string_number_conversions.h"
#include "net/base/url_util.h"
#include "url/gurl.h"
namespace net {
NaiveListenConfig::NaiveListenConfig() = default;
NaiveListenConfig::NaiveListenConfig(const NaiveListenConfig&) = default;
NaiveListenConfig::~NaiveListenConfig() = default;
bool NaiveListenConfig::Parse(const std::string& str) {
GURL url(str);
if (url.scheme() == "socks") {
protocol = ClientProtocol::kSocks5;
} else if (url.scheme() == "http") {
protocol = ClientProtocol::kHttp;
} else if (url.scheme() == "redir") {
#if BUILDFLAG(IS_LINUX)
protocol = ClientProtocol::kRedir;
#else
std::cerr << "Redir protocol only supports Linux." << std::endl;
return false;
#endif
} else {
std::cerr << "Invalid scheme in " << str << std::endl;
return false;
}
if (!url.username().empty()) {
user = base::UnescapeBinaryURLComponent(url.username());
}
if (!url.password().empty()) {
pass = base::UnescapeBinaryURLComponent(url.password());
}
if (!url.host().empty()) {
addr = url.HostNoBrackets();
}
int effective_port = url.EffectiveIntPort();
if (effective_port == url::PORT_INVALID) {
std::cerr << "Invalid port in " << str << std::endl;
return false;
}
if (effective_port != url::PORT_UNSPECIFIED) {
port = effective_port;
}
return true;
}
NaiveConfig::NaiveConfig() = default;
NaiveConfig::NaiveConfig(const NaiveConfig&) = default;
NaiveConfig::~NaiveConfig() = default;
bool NaiveConfig::Parse(const base::Value::Dict& value) {
if (const base::Value* v = value.Find("listen")) {
listen.clear();
if (const std::string* str = v->GetIfString()) {
if (!listen.emplace_back().Parse(*str)) {
return false;
}
} else if (const base::Value::List* strs = v->GetIfList()) {
for (const auto& str_e : *strs) {
if (const std::string* s = str_e.GetIfString()) {
if (!listen.emplace_back().Parse(*s)) {
return false;
}
} else {
std::cerr << "Invalid listen element" << std::endl;
return false;
}
}
} else {
std::cerr << "Invalid listen" << std::endl;
return false;
}
}
if (const base::Value* v = value.Find("insecure-concurrency")) {
if (std::optional<int> i = v->GetIfInt()) {
insecure_concurrency = *i;
} else if (const std::string* str = v->GetIfString()) {
if (!base::StringToInt(*str, &insecure_concurrency)) {
std::cerr << "Invalid concurrency" << std::endl;
return false;
}
} else {
std::cerr << "Invalid concurrency" << std::endl;
return false;
}
if (insecure_concurrency < 1) {
std::cerr << "Invalid concurrency" << std::endl;
return false;
}
}
if (const base::Value* v = value.Find("extra-headers")) {
if (const std::string* str = v->GetIfString()) {
extra_headers.AddHeadersFromString(*str);
} else {
std::cerr << "Invalid extra-headers" << std::endl;
return false;
}
}
if (const base::Value* v = value.Find("proxy")) {
if (const std::string* str = v->GetIfString(); str && !str->empty()) {
GURL url(*str);
net::GetIdentityFromURL(url, &proxy_user, &proxy_pass);
GURL::Replacements remove_auth;
remove_auth.ClearUsername();
remove_auth.ClearPassword();
GURL url_no_auth = url.ReplaceComponents(remove_auth);
proxy_url = url_no_auth.GetWithEmptyPath().spec();
if (proxy_url.empty()) {
std::cerr << "Invalid proxy" << std::endl;
return false;
} else if (proxy_url.back() == '/') {
proxy_url.pop_back();
}
} else {
std::cerr << "Invalid proxy" << std::endl;
return false;
}
}
if (const base::Value* v = value.Find("host-resolver-rules")) {
if (const std::string* str = v->GetIfString()) {
host_resolver_rules = *str;
} else {
std::cerr << "Invalid host-resolver-rules" << std::endl;
return false;
}
}
if (const base::Value* v = value.Find("resolver-range")) {
if (const std::string* str = v->GetIfString(); str && !str->empty()) {
if (!net::ParseCIDRBlock(*str, &resolver_range, &resolver_prefix)) {
std::cerr << "Invalid resolver-range" << std::endl;
return false;
}
if (resolver_range.IsIPv6()) {
std::cerr << "IPv6 resolver range not supported" << std::endl;
return false;
}
} else {
std::cerr << "Invalid resolver-range" << std::endl;
return false;
}
}
if (const base::Value* v = value.Find("log")) {
if (const std::string* str = v->GetIfString()) {
if (!str->empty()) {
log.logging_dest = logging::LOG_TO_FILE;
log_file = base::FilePath::FromUTF8Unsafe(*str);
log.log_file_path = log_file.value().c_str();
} else {
log.logging_dest = logging::LOG_TO_STDERR;
}
} else {
std::cerr << "Invalid log" << std::endl;
return false;
}
}
if (const base::Value* v = value.Find("log-net-log")) {
if (const std::string* str = v->GetIfString(); str && !str->empty()) {
log_net_log = base::FilePath::FromUTF8Unsafe(*str);
} else {
std::cerr << "Invalid log-net-log" << std::endl;
return false;
}
}
if (const base::Value* v = value.Find("ssl-key-log-file")) {
if (const std::string* str = v->GetIfString(); str && !str->empty()) {
ssl_key_log_file = base::FilePath::FromUTF8Unsafe(*str);
} else {
std::cerr << "Invalid ssl-key-log-file" << std::endl;
return false;
}
}
if (const base::Value* v = value.Find("no-post-quantum")) {
no_post_quantum = true;
}
return true;
}
} // namespace net

View File

@@ -0,0 +1,66 @@
// Copyright 2024 klzgrad <kizdiv@gmail.com>. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_TOOLS_NAIVE_NAIVE_CONFIG_H_
#define NET_TOOLS_NAIVE_NAIVE_CONFIG_H_
#include <optional>
#include <string>
#include <vector>
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/values.h"
#include "net/base/ip_address.h"
#include "net/http/http_request_headers.h"
#include "net/tools/naive/naive_protocol.h"
namespace net {
struct NaiveListenConfig {
ClientProtocol protocol = ClientProtocol::kSocks5;
std::string user;
std::string pass;
std::string addr = "0.0.0.0";
int port = 1080;
NaiveListenConfig();
NaiveListenConfig(const NaiveListenConfig&);
~NaiveListenConfig();
bool Parse(const std::string& str);
};
struct NaiveConfig {
std::vector<NaiveListenConfig> listen = {NaiveListenConfig()};
int insecure_concurrency = 1;
HttpRequestHeaders extra_headers;
std::string proxy_url = "direct://";
std::u16string proxy_user;
std::u16string proxy_pass;
std::string host_resolver_rules;
IPAddress resolver_range = {100, 64, 0, 0};
size_t resolver_prefix = 10;
logging::LoggingSettings log = {.logging_dest = logging::LOG_NONE};
base::FilePath log_file;
base::FilePath log_net_log;
base::FilePath ssl_key_log_file;
std::optional<bool> no_post_quantum;
NaiveConfig();
NaiveConfig(const NaiveConfig&);
~NaiveConfig();
bool Parse(const base::Value::Dict& value);
};
} // namespace net
#endif // NET_TOOLS_NAIVE_NAIVE_CONFIG_H_

View File

@@ -7,6 +7,7 @@
#include <iostream> #include <iostream>
#include <limits> #include <limits>
#include <memory> #include <memory>
#include <optional>
#include <string> #include <string>
#include "base/allocator/allocator_check.h" #include "base/allocator/allocator_check.h"
@@ -60,8 +61,11 @@
#include "net/socket/ssl_client_socket.h" #include "net/socket/ssl_client_socket.h"
#include "net/socket/tcp_server_socket.h" #include "net/socket/tcp_server_socket.h"
#include "net/socket/udp_server_socket.h" #include "net/socket/udp_server_socket.h"
#include "net/ssl/ssl_config_service.h"
#include "net/ssl/ssl_key_logger_impl.h" #include "net/ssl/ssl_key_logger_impl.h"
#include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h"
#include "net/tools/naive/naive_command_line.h"
#include "net/tools/naive/naive_config.h"
#include "net/tools/naive/naive_protocol.h" #include "net/tools/naive/naive_protocol.h"
#include "net/tools/naive/naive_proxy.h" #include "net/tools/naive/naive_proxy.h"
#include "net/tools/naive/naive_proxy_delegate.h" #include "net/tools/naive/naive_proxy_delegate.h"
@@ -87,42 +91,6 @@ constexpr int kExpectedMaxUsers = 8;
constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation = constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation =
net::DefineNetworkTrafficAnnotation("naive", ""); net::DefineNetworkTrafficAnnotation("naive", "");
struct CommandLine {
std::vector<std::string> listens;
std::string proxy;
std::string concurrency;
std::string extra_headers;
std::string host_resolver_rules;
std::string resolver_range;
bool no_log;
base::FilePath log;
base::FilePath log_net_log;
base::FilePath ssl_key_log_file;
};
struct ListenParams {
net::ClientProtocol protocol;
std::string listen_user;
std::string listen_pass;
std::string listen_addr;
int listen_port;
};
struct Params {
std::vector<ListenParams> listens;
int concurrency;
net::HttpRequestHeaders extra_headers;
std::string proxy_url;
std::u16string proxy_user;
std::u16string proxy_pass;
std::string host_resolver_rules;
net::IPAddress resolver_range;
size_t resolver_prefix;
logging::LoggingSettings log_settings;
base::FilePath net_log_path;
base::FilePath ssl_key_path;
};
std::unique_ptr<base::Value::Dict> GetConstants() { std::unique_ptr<base::Value::Dict> GetConstants() {
base::Value::Dict constants_dict = net::GetNetConstants(); base::Value::Dict constants_dict = net::GetNetConstants();
base::Value::Dict dict; base::Value::Dict dict;
@@ -134,278 +102,6 @@ std::unique_ptr<base::Value::Dict> GetConstants() {
constants_dict.Set("clientInfo", std::move(dict)); constants_dict.Set("clientInfo", std::move(dict));
return std::make_unique<base::Value::Dict>(std::move(constants_dict)); return std::make_unique<base::Value::Dict>(std::move(constants_dict));
} }
class MultipleListenCollector : public base::DuplicateSwitchHandler {
public:
void ResolveDuplicate(std::string_view key,
base::CommandLine::StringPieceType new_value,
base::CommandLine::StringType& out_value) override {
out_value = new_value;
if (key == "listen") {
#if BUILDFLAG(IS_WIN)
all_values_.push_back(base::WideToUTF8(new_value));
#else
all_values_.push_back(std::string(new_value));
#endif
}
}
const std::vector<std::string>& GetAllValues() const {
return all_values_;
}
private:
std::vector<std::string> all_values_;
};
void GetCommandLine(const base::CommandLine& proc,
CommandLine* cmdline,
MultipleListenCollector& multiple_listens) {
if (proc.HasSwitch("h") || proc.HasSwitch("help")) {
std::cout << "Usage: naive { OPTIONS | config.json }\n"
"\n"
"Options:\n"
"-h, --help Show this message\n"
"--version Print version\n"
"--listen=<proto>://[addr][:port] [--listen=...]\n"
" proto: socks, http\n"
" redir (Linux only)\n"
"--proxy=<proto>://[<user>:<pass>@]<hostname>[:<port>]\n"
" proto: https, quic\n"
"--insecure-concurrency=<N> Use N connections, insecure\n"
"--extra-headers=... Extra headers split by CRLF\n"
"--host-resolver-rules=... Resolver rules\n"
"--resolver-range=... Redirect resolver range\n"
"--log[=<path>] Log to stderr, or file\n"
"--log-net-log=<path> Save NetLog\n"
"--ssl-key-log-file=<path> Save SSL keys for Wireshark\n"
<< std::endl;
exit(EXIT_SUCCESS);
}
if (proc.HasSwitch("version")) {
std::cout << "naive " << version_info::GetVersionNumber() << std::endl;
exit(EXIT_SUCCESS);
}
cmdline->listens = multiple_listens.GetAllValues();
cmdline->proxy = proc.GetSwitchValueASCII("proxy");
cmdline->concurrency = proc.GetSwitchValueASCII("insecure-concurrency");
cmdline->extra_headers = proc.GetSwitchValueASCII("extra-headers");
cmdline->host_resolver_rules =
proc.GetSwitchValueASCII("host-resolver-rules");
cmdline->resolver_range = proc.GetSwitchValueASCII("resolver-range");
cmdline->no_log = !proc.HasSwitch("log");
cmdline->log = proc.GetSwitchValuePath("log");
cmdline->log_net_log = proc.GetSwitchValuePath("log-net-log");
cmdline->ssl_key_log_file = proc.GetSwitchValuePath("ssl-key-log-file");
}
void GetCommandLineFromConfig(const base::FilePath& config_path,
CommandLine* cmdline) {
JSONFileValueDeserializer reader(config_path);
int error_code;
std::string error_message;
std::unique_ptr<base::Value> value =
reader.Deserialize(&error_code, &error_message);
if (value == nullptr) {
std::cerr << "Error reading " << config_path << ": (" << error_code << ") "
<< error_message << std::endl;
exit(EXIT_FAILURE);
}
base::Value::Dict* value_dict = value->GetIfDict();
if (value_dict == nullptr) {
std::cerr << "Invalid config format" << std::endl;
exit(EXIT_FAILURE);
}
const std::string* listen = value_dict->FindString("listen");
if (listen != nullptr) {
cmdline->listens = {*listen};
} else {
const base::Value::List* listen_list = value_dict->FindList("listen");
if (listen_list != nullptr) {
for (const auto& listen_element : *listen_list) {
const std::string* listen_elemet_str = listen_element.GetIfString();
if (listen_elemet_str == nullptr) {
std::cerr << "Invalid listen element" << std::endl;
exit(EXIT_FAILURE);
}
cmdline->listens.push_back(*listen_elemet_str);
}
}
}
const std::string* proxy = value_dict->FindString("proxy");
if (proxy) {
cmdline->proxy = *proxy;
}
const std::string* concurrency =
value_dict->FindString("insecure-concurrency");
if (concurrency) {
cmdline->concurrency = *concurrency;
}
const std::string* extra_headers = value_dict->FindString("extra-headers");
if (extra_headers) {
cmdline->extra_headers = *extra_headers;
}
const std::string* host_resolver_rules =
value_dict->FindString("host-resolver-rules");
if (host_resolver_rules) {
cmdline->host_resolver_rules = *host_resolver_rules;
}
const std::string* resolver_range = value_dict->FindString("resolver-range");
if (resolver_range) {
cmdline->resolver_range = *resolver_range;
}
cmdline->no_log = true;
const std::string* log = value_dict->FindString("log");
if (log) {
cmdline->no_log = false;
cmdline->log = base::FilePath::FromUTF8Unsafe(*log);
}
const std::string* log_net_log = value_dict->FindString("log-net-log");
if (log_net_log) {
cmdline->log_net_log = base::FilePath::FromUTF8Unsafe(*log_net_log);
}
const std::string* ssl_key_log_file =
value_dict->FindString("ssl-key-log-file");
if (ssl_key_log_file) {
cmdline->ssl_key_log_file =
base::FilePath::FromUTF8Unsafe(*ssl_key_log_file);
}
}
bool ParseListenParams(const std::string& listen_str,
ListenParams& listen_params) {
GURL url(listen_str);
if (url.scheme() == "socks") {
listen_params.protocol = net::ClientProtocol::kSocks5;
} else if (url.scheme() == "http") {
listen_params.protocol = net::ClientProtocol::kHttp;
} else if (url.scheme() == "redir") {
#if BUILDFLAG(IS_LINUX)
listen_params.protocol = net::ClientProtocol::kRedir;
#else
std::cerr << "Redir protocol only supports Linux." << std::endl;
return false;
#endif
} else {
std::cerr << "Invalid scheme in --listen" << std::endl;
return false;
}
if (!url.username().empty()) {
listen_params.listen_user =
base::UnescapeBinaryURLComponent(url.username());
}
if (!url.password().empty()) {
listen_params.listen_pass =
base::UnescapeBinaryURLComponent(url.password());
}
if (!url.host().empty()) {
listen_params.listen_addr = url.HostNoBrackets();
} else {
listen_params.listen_addr = "0.0.0.0";
}
int port = url.EffectiveIntPort();
if (port == url::PORT_INVALID) {
std::cerr << "Invalid port in --listen" << std::endl;
return false;
} else if (port == url::PORT_UNSPECIFIED) {
port = 1080;
}
listen_params.listen_port = port;
return true;
}
bool ParseCommandLine(const CommandLine& cmdline, Params* params) {
url::AddStandardScheme("socks",
url::SCHEME_WITH_HOST_PORT_AND_USER_INFORMATION);
url::AddStandardScheme("redir", url::SCHEME_WITH_HOST_AND_PORT);
bool any_redir_protocol = false;
if (!cmdline.listens.empty()) {
for (const std::string& listen : cmdline.listens) {
ListenParams listen_params;
if (!ParseListenParams(listen, listen_params)) {
std::cerr << "Invalid listen: " << listen << std::endl;
return false;
}
if (listen_params.protocol == net::ClientProtocol::kRedir) {
any_redir_protocol = true;
}
params->listens.push_back(listen_params);
}
} else {
ListenParams default_listen = {
.protocol = net::ClientProtocol::kSocks5,
.listen_addr = "0.0.0.0",
.listen_port = 1080,
};
params->listens = {default_listen};
}
params->proxy_url = "direct://";
GURL url(cmdline.proxy);
GURL::Replacements remove_auth;
remove_auth.ClearUsername();
remove_auth.ClearPassword();
GURL url_no_auth = url.ReplaceComponents(remove_auth);
if (!cmdline.proxy.empty()) {
params->proxy_url = url_no_auth.GetWithEmptyPath().spec();
if (params->proxy_url.empty()) {
std::cerr << "Invalid proxy URL" << std::endl;
return false;
} else if (params->proxy_url.back() == '/') {
params->proxy_url.pop_back();
}
net::GetIdentityFromURL(url, &params->proxy_user, &params->proxy_pass);
}
if (!cmdline.concurrency.empty()) {
if (!base::StringToInt(cmdline.concurrency, &params->concurrency) ||
params->concurrency < 1) {
std::cerr << "Invalid concurrency" << std::endl;
return false;
}
} else {
params->concurrency = 1;
}
params->extra_headers.AddHeadersFromString(cmdline.extra_headers);
params->host_resolver_rules = cmdline.host_resolver_rules;
if (any_redir_protocol) {
std::string range = "100.64.0.0/10";
if (!cmdline.resolver_range.empty())
range = cmdline.resolver_range;
if (!net::ParseCIDRBlock(range, &params->resolver_range,
&params->resolver_prefix)) {
std::cerr << "Invalid resolver range" << std::endl;
return false;
}
if (params->resolver_range.IsIPv6()) {
std::cerr << "IPv6 resolver range not supported" << std::endl;
return false;
}
}
if (!cmdline.no_log) {
if (!cmdline.log.empty()) {
params->log_settings.logging_dest = logging::LOG_TO_FILE;
params->log_settings.log_file_path = cmdline.log.value().c_str();
} else {
params->log_settings.logging_dest = logging::LOG_TO_STDERR;
}
} else {
params->log_settings.logging_dest = logging::LOG_NONE;
}
params->net_log_path = cmdline.log_net_log;
params->ssl_key_path = cmdline.ssl_key_log_file;
return true;
}
} // namespace } // namespace
namespace net { namespace net {
@@ -471,7 +167,7 @@ std::unique_ptr<URLRequestContext> BuildCertURLRequestContext(NetLog* net_log) {
// Builds a URLRequestContext assuming there's only a single loop. // Builds a URLRequestContext assuming there's only a single loop.
std::unique_ptr<URLRequestContext> BuildURLRequestContext( std::unique_ptr<URLRequestContext> BuildURLRequestContext(
const Params& params, const NaiveConfig& config,
scoped_refptr<CertNetFetcherURLRequest> cert_net_fetcher, scoped_refptr<CertNetFetcherURLRequest> cert_net_fetcher,
NetLog* net_log) { NetLog* net_log) {
URLRequestContextBuilder builder; URLRequestContextBuilder builder;
@@ -479,7 +175,7 @@ std::unique_ptr<URLRequestContext> BuildURLRequestContext(
builder.DisableHttpCache(); builder.DisableHttpCache();
builder.set_net_log(net_log); builder.set_net_log(net_log);
std::string proxy_url = params.proxy_url; std::string proxy_url = config.proxy_url;
bool force_quic = false; bool force_quic = false;
if (proxy_url.compare(0, 7, "quic://") == 0) { if (proxy_url.compare(0, 7, "quic://") == 0) {
proxy_url.replace(0, 4, "https"); proxy_url.replace(0, 4, "https");
@@ -505,21 +201,36 @@ std::unique_ptr<URLRequestContext> BuildURLRequestContext(
proxy_service->ForceReloadProxyConfig(); proxy_service->ForceReloadProxyConfig();
builder.set_proxy_resolution_service(std::move(proxy_service)); builder.set_proxy_resolution_service(std::move(proxy_service));
if (!params.host_resolver_rules.empty()) { if (!config.host_resolver_rules.empty()) {
builder.set_host_mapping_rules(params.host_resolver_rules); builder.set_host_mapping_rules(config.host_resolver_rules);
} }
builder.SetCertVerifier( builder.SetCertVerifier(
CertVerifier::CreateDefault(std::move(cert_net_fetcher))); CertVerifier::CreateDefault(std::move(cert_net_fetcher)));
builder.set_proxy_delegate(std::make_unique<NaiveProxyDelegate>( builder.set_proxy_delegate(std::make_unique<NaiveProxyDelegate>(
params.extra_headers, config.extra_headers,
std::vector<PaddingType>{PaddingType::kVariant1, PaddingType::kNone})); std::vector<PaddingType>{PaddingType::kVariant1, PaddingType::kNone}));
if (config.no_post_quantum == true) {
struct NoPostQuantum : public SSLConfigService {
SSLContextConfig GetSSLContextConfig() override {
SSLContextConfig config;
config.post_quantum_override = false;
return config;
}
bool CanShareConnectionWithClientCerts(std::string_view) const override {
return false;
}
};
builder.set_ssl_config_service(std::make_unique<NoPostQuantum>());
}
auto context = builder.Build(); auto context = builder.Build();
if (!params.proxy_url.empty() && !params.proxy_user.empty() && if (!config.proxy_url.empty() && !config.proxy_user.empty() &&
!params.proxy_pass.empty()) { !config.proxy_pass.empty()) {
auto* session = context->http_transaction_factory()->GetSession(); auto* session = context->http_transaction_factory()->GetSession();
auto* auth_cache = session->http_auth_cache(); auto* auth_cache = session->http_auth_cache();
GURL proxy_gurl(proxy_url); GURL proxy_gurl(proxy_url);
@@ -530,7 +241,7 @@ std::unique_ptr<URLRequestContext> BuildURLRequestContext(
net::HostPortPair::FromURL(proxy_gurl)); net::HostPortPair::FromURL(proxy_gurl));
} }
url::SchemeHostPort auth_origin(proxy_gurl); url::SchemeHostPort auth_origin(proxy_gurl);
AuthCredentials credentials(params.proxy_user, params.proxy_pass); AuthCredentials credentials(config.proxy_user, config.proxy_pass);
auth_cache->Add(auth_origin, HttpAuth::AUTH_PROXY, auth_cache->Add(auth_origin, HttpAuth::AUTH_PROXY,
/*realm=*/{}, HttpAuth::AUTH_SCHEME_BASIC, {}, /*realm=*/{}, HttpAuth::AUTH_SCHEME_BASIC, {},
/*challenge=*/"Basic", credentials, /*path=*/"/"); /*challenge=*/"Basic", credentials, /*path=*/"/");
@@ -565,9 +276,7 @@ int main(int argc, char* argv[]) {
// content/app/content_main.cc: RunContentProcess() // content/app/content_main.cc: RunContentProcess()
base::EnableTerminationOnOutOfMemory(); base::EnableTerminationOnOutOfMemory();
auto multiple_listens = std::make_unique<MultipleListenCollector>(); DuplicateSwitchCollector::InitInstance();
MultipleListenCollector& multiple_listens_ref = *multiple_listens;
base::CommandLine::SetDuplicateSwitchHandler(std::move(multiple_listens));
// content/app/content_main.cc: RunContentProcess() // content/app/content_main.cc: RunContentProcess()
base::CommandLine::Init(argc, argv); base::CommandLine::Init(argc, argv);
@@ -606,6 +315,9 @@ int main(int argc, char* argv[]) {
url::AddStandardScheme("quic", url::AddStandardScheme("quic",
url::SCHEME_WITH_HOST_PORT_AND_USER_INFORMATION); url::SCHEME_WITH_HOST_PORT_AND_USER_INFORMATION);
url::AddStandardScheme("socks",
url::SCHEME_WITH_HOST_PORT_AND_USER_INFORMATION);
url::AddStandardScheme("redir", url::SCHEME_WITH_HOST_AND_PORT);
net::ClientSocketPoolManager::set_max_sockets_per_pool( net::ClientSocketPoolManager::set_max_sockets_per_pool(
net::HttpNetworkSession::NORMAL_SOCKET_POOL, net::HttpNetworkSession::NORMAL_SOCKET_POOL,
kDefaultMaxSocketsPerPool * kExpectedMaxUsers); kDefaultMaxSocketsPerPool * kExpectedMaxUsers);
@@ -616,30 +328,70 @@ int main(int argc, char* argv[]) {
net::HttpNetworkSession::NORMAL_SOCKET_POOL, net::HttpNetworkSession::NORMAL_SOCKET_POOL,
kDefaultMaxSocketsPerGroup * kExpectedMaxUsers); kDefaultMaxSocketsPerGroup * kExpectedMaxUsers);
CommandLine cmdline;
Params params;
const auto& proc = *base::CommandLine::ForCurrentProcess(); const auto& proc = *base::CommandLine::ForCurrentProcess();
const auto& args = proc.GetArgs(); const auto& args = proc.GetArgs();
if (args.empty()) { base::Value::Dict config_dict;
if (proc.argv().size() >= 2) { if (args.empty() && proc.argv().size() >= 2) {
GetCommandLine(proc, &cmdline, multiple_listens_ref); config_dict = GetSwitchesAsValue(proc);
} else {
auto path = base::FilePath::FromUTF8Unsafe("config.json");
GetCommandLineFromConfig(path, &cmdline);
}
} else { } else {
base::FilePath path(args[0]); base::FilePath config_file;
GetCommandLineFromConfig(path, &cmdline); if (!args.empty()) {
config_file = base::FilePath(args[0]);
} else {
config_file = base::FilePath::FromUTF8Unsafe("config.json");
}
JSONFileValueDeserializer reader(config_file);
int error_code;
std::string error_message;
std::unique_ptr<base::Value> value =
reader.Deserialize(&error_code, &error_message);
if (value == nullptr) {
std::cerr << "Error reading " << config_file << ": (" << error_code
<< ") " << error_message << std::endl;
return EXIT_FAILURE;
}
if (const base::Value::Dict* dict = value->GetIfDict()) {
config_dict = dict->Clone();
}
} }
if (!ParseCommandLine(cmdline, &params)) {
if (config_dict.contains("h") || config_dict.contains("help")) {
std::cout << "Usage: naive { OPTIONS | config.json }\n"
"\n"
"Options:\n"
"-h, --help Show this message\n"
"--version Print version\n"
"--listen=<proto>://[addr][:port] [--listen=...]\n"
" proto: socks, http\n"
" redir (Linux only)\n"
"--proxy=<proto>://[<user>:<pass>@]<hostname>[:<port>]\n"
" proto: https, quic\n"
"--insecure-concurrency=<N> Use N connections, insecure\n"
"--extra-headers=... Extra headers split by CRLF\n"
"--host-resolver-rules=... Resolver rules\n"
"--resolver-range=... Redirect resolver range\n"
"--log[=<path>] Log to stderr, or file\n"
"--log-net-log=<path> Save NetLog\n"
"--ssl-key-log-file=<path> Save SSL keys for Wireshark\n"
"--no-post-quantum No post-quantum key agreement\n"
<< std::endl;
exit(EXIT_SUCCESS);
}
if (config_dict.contains("version")) {
std::cout << "naive " << version_info::GetVersionNumber() << std::endl;
exit(EXIT_SUCCESS);
}
net::NaiveConfig config;
if (!config.Parse(config_dict)) {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
CHECK(logging::InitLogging(params.log_settings)); CHECK(logging::InitLogging(config.log));
if (!params.ssl_key_path.empty()) { if (!config.ssl_key_log_file.empty()) {
net::SSLClientSocket::SetSSLKeyLogger( net::SSLClientSocket::SetSSLKeyLogger(
std::make_unique<net::SSLKeyLoggerImpl>(params.ssl_key_path)); std::make_unique<net::SSLKeyLoggerImpl>(config.ssl_key_log_file));
} }
// The declaration order for net_log and printing_log_observer is // The declaration order for net_log and printing_log_observer is
@@ -648,15 +400,15 @@ int main(int argc, char* argv[]) {
// printing_log_observer. // printing_log_observer.
net::NetLog* net_log = net::NetLog::Get(); net::NetLog* net_log = net::NetLog::Get();
std::unique_ptr<net::FileNetLogObserver> observer; std::unique_ptr<net::FileNetLogObserver> observer;
if (!params.net_log_path.empty()) { if (!config.log_net_log.empty()) {
observer = net::FileNetLogObserver::CreateUnbounded( observer = net::FileNetLogObserver::CreateUnbounded(
params.net_log_path, net::NetLogCaptureMode::kDefault, GetConstants()); config.log_net_log, net::NetLogCaptureMode::kDefault, GetConstants());
observer->StartObserving(net_log); observer->StartObserving(net_log);
} }
// Avoids net log overhead if verbose logging is disabled. // Avoids net log overhead if verbose logging is disabled.
std::unique_ptr<net::PrintingLogObserver> printing_log_observer; std::unique_ptr<net::PrintingLogObserver> printing_log_observer;
if (params.log_settings.logging_dest != logging::LOG_NONE && VLOG_IS_ON(1)) { if (config.log.logging_dest != logging::LOG_NONE && VLOG_IS_ON(1)) {
printing_log_observer = std::make_unique<net::PrintingLogObserver>(); printing_log_observer = std::make_unique<net::PrintingLogObserver>();
net_log->AddObserver(printing_log_observer.get(), net_log->AddObserver(printing_log_observer.get(),
net::NetLogCaptureMode::kDefault); net::NetLogCaptureMode::kDefault);
@@ -675,43 +427,41 @@ int main(int argc, char* argv[]) {
cert_net_fetcher->SetURLRequestContext(cert_context.get()); cert_net_fetcher->SetURLRequestContext(cert_context.get());
#endif #endif
auto context = auto context =
net::BuildURLRequestContext(params, std::move(cert_net_fetcher), net_log); net::BuildURLRequestContext(config, std::move(cert_net_fetcher), net_log);
auto* session = context->http_transaction_factory()->GetSession(); auto* session = context->http_transaction_factory()->GetSession();
std::vector<std::unique_ptr<net::NaiveProxy>> naive_proxies; std::vector<std::unique_ptr<net::NaiveProxy>> naive_proxies;
std::unique_ptr<net::RedirectResolver> resolver; std::unique_ptr<net::RedirectResolver> resolver;
for (const ListenParams& listen_params : params.listens) { for (const net::NaiveListenConfig& listen_config : config.listen) {
auto listen_socket = auto listen_socket =
std::make_unique<net::TCPServerSocket>(net_log, net::NetLogSource()); std::make_unique<net::TCPServerSocket>(net_log, net::NetLogSource());
int result = listen_socket->ListenWithAddressAndPort( int result = listen_socket->ListenWithAddressAndPort(
listen_params.listen_addr, listen_params.listen_port, kListenBackLog); listen_config.addr, listen_config.port, kListenBackLog);
if (result != net::OK) { if (result != net::OK) {
LOG(ERROR) << "Failed to listen on " LOG(ERROR) << "Failed to listen on "
<< net::ToString(listen_params.protocol) << "://" << net::ToString(listen_config.protocol) << "://"
<< listen_params.listen_addr << " " << listen_config.addr << " " << listen_config.port << ": "
<< listen_params.listen_port << ": "
<< net::ErrorToShortString(result); << net::ErrorToShortString(result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
LOG(INFO) << "Listening on " << net::ToString(listen_params.protocol) LOG(INFO) << "Listening on " << net::ToString(listen_config.protocol)
<< "://" << listen_params.listen_addr << ":" << "://" << listen_config.addr << ":" << listen_config.port;
<< listen_params.listen_port;
if (resolver == nullptr && if (resolver == nullptr &&
listen_params.protocol == net::ClientProtocol::kRedir) { listen_config.protocol == net::ClientProtocol::kRedir) {
auto resolver_socket = auto resolver_socket =
std::make_unique<net::UDPServerSocket>(net_log, net::NetLogSource()); std::make_unique<net::UDPServerSocket>(net_log, net::NetLogSource());
resolver_socket->AllowAddressReuse(); resolver_socket->AllowAddressReuse();
net::IPAddress listen_addr; net::IPAddress listen_addr;
if (!listen_addr.AssignFromIPLiteral(listen_params.listen_addr)) { if (!listen_addr.AssignFromIPLiteral(listen_config.addr)) {
LOG(ERROR) << "Failed to open resolver: " << listen_params.listen_addr; LOG(ERROR) << "Failed to open resolver: " << listen_config.addr;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
result = resolver_socket->Listen( result = resolver_socket->Listen(
net::IPEndPoint(listen_addr, listen_params.listen_port)); net::IPEndPoint(listen_addr, listen_config.port));
if (result != net::OK) { if (result != net::OK) {
LOG(ERROR) << "Failed to open resolver: " LOG(ERROR) << "Failed to open resolver: "
<< net::ErrorToShortString(result); << net::ErrorToShortString(result);
@@ -719,14 +469,14 @@ int main(int argc, char* argv[]) {
} }
resolver = std::make_unique<net::RedirectResolver>( resolver = std::make_unique<net::RedirectResolver>(
std::move(resolver_socket), params.resolver_range, std::move(resolver_socket), config.resolver_range,
params.resolver_prefix); config.resolver_prefix);
} }
auto naive_proxy = std::make_unique<net::NaiveProxy>( auto naive_proxy = std::make_unique<net::NaiveProxy>(
std::move(listen_socket), listen_params.protocol, std::move(listen_socket), listen_config.protocol, listen_config.user,
listen_params.listen_user, listen_params.listen_pass, listen_config.pass, config.insecure_concurrency, resolver.get(),
params.concurrency, resolver.get(), session, kTrafficAnnotation, session, kTrafficAnnotation,
std::vector<net::PaddingType>{net::PaddingType::kVariant1, std::vector<net::PaddingType>{net::PaddingType::kVariant1,
net::PaddingType::kNone}); net::PaddingType::kNone});
naive_proxies.push_back(std::move(naive_proxy)); naive_proxies.push_back(std::move(naive_proxy));

View File

@@ -95,8 +95,8 @@ case "$1" in
check_list_update "$1" "Loyalsoldier/v2ray-rules-dat" "release" "gfw.txt" check_list_update "$1" "Loyalsoldier/v2ray-rules-dat" "release" "gfw.txt"
;; ;;
"china_list") "china_list")
check_list_update "$1" "Loyalsoldier/v2ray-rules-dat" "release" "direct-list.txt" check_list_update "$1" "Loyalsoldier/v2ray-rules-dat" "release" "direct-list.txt" && \
sed -i -e "s/full://g" -e "/:/d" "$RESOURCES_DIR/china_list.txt" sed -i -e "s/full://g" -e "/:/d" "$RESOURCES_DIR/china_list.txt"
;; ;;
*) *)
echo -e "Usage: $0 <china_ip4 / china_ip6 / gfw_list / china_list>" echo -e "Usage: $0 <china_ip4 / china_ip6 / gfw_list / china_list>"

View File

@@ -21,13 +21,13 @@ define Download/geoip
HASH:=2f7516c0f853625e0a7ca932f534eb6d963f4287d4a2c585b1d193b4bb0a0f4f HASH:=2f7516c0f853625e0a7ca932f534eb6d963f4287d4a2c585b1d193b4bb0a0f4f
endef endef
GEOSITE_VER:=20240426060244 GEOSITE_VER:=20240504082351
GEOSITE_FILE:=dlc.dat.$(GEOSITE_VER) GEOSITE_FILE:=dlc.dat.$(GEOSITE_VER)
define Download/geosite define Download/geosite
URL:=https://github.com/v2fly/domain-list-community/releases/download/$(GEOSITE_VER)/ URL:=https://github.com/v2fly/domain-list-community/releases/download/$(GEOSITE_VER)/
URL_FILE:=dlc.dat URL_FILE:=dlc.dat
FILE:=$(GEOSITE_FILE) FILE:=$(GEOSITE_FILE)
HASH:=7aa19bb7fa5f99d62d3db87b632334caa356fb9b901f85f7168c064370973646 HASH:=a4d70989c3928289f07528894f29788d7844bdbfb450dd6597595d1d0210881d
endef endef
GEOSITE_IRAN_VER:=202404290026 GEOSITE_IRAN_VER:=202404290026

View File

@@ -57,11 +57,14 @@ namespace v2rayN
/// 取得存储资源 /// 取得存储资源
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public static string? LoadResource(string res) public static string? LoadResource(string? res)
{ {
try try
{ {
if (!File.Exists(res)) return null; if (!File.Exists(res))
{
return null;
}
return File.ReadAllText(res); return File.ReadAllText(res);
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -895,18 +895,45 @@ namespace v2rayN.Handler
ruleSets.AddRange(dnsRule.rule_set); ruleSets.AddRange(dnsRule.rule_set);
} }
//load custom ruleset file
List<Ruleset4Sbox> customRulesets = [];
if (_config.routingBasicItem.enableRoutingAdvanced)
{
var routing = ConfigHandler.GetDefaultRouting(_config);
if (!Utils.IsNullOrEmpty(routing.customRulesetPath4Singbox))
{
var result = Utils.LoadResource(routing.customRulesetPath4Singbox);
if (!Utils.IsNullOrEmpty(result))
{
customRulesets = (JsonUtils.Deserialize<List<Ruleset4Sbox>>(result) ?? [])
.Where(t => t.tag != null)
.Where(t => t.type != null)
.Where(t => t.format != null)
.ToList();
}
}
}
//Add ruleset srs //Add ruleset srs
singboxConfig.route.rule_set = []; singboxConfig.route.rule_set = [];
foreach (var item in new HashSet<string>(ruleSets)) foreach (var item in new HashSet<string>(ruleSets))
{ {
singboxConfig.route.rule_set.Add(new() var customRuleset = customRulesets.FirstOrDefault(t => t.tag != null && t.tag.Equals(item));
if (customRuleset != null)
{ {
type = "remote", singboxConfig.route.rule_set.Add(customRuleset);
format = "binary", }
tag = item, else
url = string.Format(Global.SingboxRulesetUrl, item.StartsWith(geosite) ? geosite : geoip, item), {
download_detour = Global.ProxyTag singboxConfig.route.rule_set.Add(new()
}); {
type = "remote",
format = "binary",
tag = item,
url = string.Format(Global.SingboxRulesetUrl, item.StartsWith(geosite) ? geosite : geoip, item),
download_detour = Global.ProxyTag
});
}
} }
return 0; return 0;

View File

@@ -264,7 +264,21 @@ namespace v2rayN.Handler
private static string GetIpv6(string address) private static string GetIpv6(string address)
{ {
return Utils.IsIpv6(address) ? $"[{address}]" : address; if (Utils.IsIpv6(address))
{
if (address.StartsWith('[') && address.EndsWith(']'))
{
return address;
}
else
{
return $"[{address}]";
}
}
else
{
return address;
}
} }
private static int GetStdTransport(ProfileItem item, string? securityDef, ref Dictionary<string, string> dicQuery) private static int GetStdTransport(ProfileItem item, string? securityDef, ref Dictionary<string, string> dicQuery)

View File

@@ -182,16 +182,11 @@ namespace v2rayN.Models
[Serializable] [Serializable]
public class RoutingBasicItem public class RoutingBasicItem
{ {
/// <summary>
/// 域名解析策略
/// </summary>
public string domainStrategy { get; set; } public string domainStrategy { get; set; }
public string domainStrategy4Singbox { get; set; } public string domainStrategy4Singbox { get; set; }
public string domainMatcher { get; set; } public string domainMatcher { get; set; }
public string routingIndexId { get; set; } public string routingIndexId { get; set; }
public bool enableRoutingAdvanced { get; set; } public bool enableRoutingAdvanced { get; set; }
} }
[Serializable] [Serializable]

View File

@@ -15,6 +15,7 @@ namespace v2rayN.Models
public bool enabled { get; set; } = true; public bool enabled { get; set; } = true;
public bool locked { get; set; } public bool locked { get; set; }
public string customIcon { get; set; } public string customIcon { get; set; }
public string customRulesetPath4Singbox { get; set; }
public string domainStrategy { get; set; } public string domainStrategy { get; set; }
public string domainStrategy4Singbox { get; set; } public string domainStrategy4Singbox { get; set; }
public int sort { get; set; } public int sort { get; set; }

View File

@@ -238,7 +238,9 @@
public string? tag { get; set; } public string? tag { get; set; }
public string? type { get; set; } public string? type { get; set; }
public string? format { get; set; } public string? format { get; set; }
public string? path { get; set; }
public string? url { get; set; } public string? url { get; set; }
public string? download_detour { get; set; } public string? download_detour { get; set; }
public string? update_interval { get; set; }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1210,4 +1210,7 @@
<data name="TbSettingsEnableCacheFile4Sbox" xml:space="preserve"> <data name="TbSettingsEnableCacheFile4Sbox" xml:space="preserve">
<value>Enable cache file for sing-box (ruleset files)</value> <value>Enable cache file for sing-box (ruleset files)</value>
</data> </data>
<data name="LvCustomRulesetPath4Singbox" xml:space="preserve">
<value>Custom the rule-set of sing-box</value>
</data>
</root> </root>

View File

@@ -1207,4 +1207,7 @@
<data name="TbSettingsEnableCacheFile4Sbox" xml:space="preserve"> <data name="TbSettingsEnableCacheFile4Sbox" xml:space="preserve">
<value>启用sing-box规则集文件的缓存文件</value> <value>启用sing-box规则集文件的缓存文件</value>
</data> </data>
<data name="LvCustomRulesetPath4Singbox" xml:space="preserve">
<value>自定义sing-box rule-set</value>
</data>
</root> </root>

View File

@@ -1180,4 +1180,7 @@
<data name="TbSettingsEnableCacheFile4Sbox" xml:space="preserve"> <data name="TbSettingsEnableCacheFile4Sbox" xml:space="preserve">
<value>啟用sing-box規則集文件的緩存文件</value> <value>啟用sing-box規則集文件的緩存文件</value>
</data> </data>
<data name="LvCustomRulesetPath4Singbox" xml:space="preserve">
<value>自訂sing-box rule-set</value>
</data>
</root> </root>

View File

@@ -192,6 +192,7 @@ namespace v2rayN.ViewModels
remarks = item.remarks, remarks = item.remarks,
url = item.url, url = item.url,
customIcon = item.customIcon, customIcon = item.customIcon,
customRulesetPath4Singbox = item.customRulesetPath4Singbox,
sort = item.sort, sort = item.sort,
}; };
_routingItems.Add(it); _routingItems.Add(it);

View File

@@ -88,6 +88,7 @@
Style="{StaticResource ToolbarTextBlock}"> Style="{StaticResource ToolbarTextBlock}">
<Hyperlink Click="linkDnsObjectDoc_Click"> <Hyperlink Click="linkDnsObjectDoc_Click">
<TextBlock Text="{x:Static resx:ResUI.TbDnsObjectDoc}" /> <TextBlock Text="{x:Static resx:ResUI.TbDnsObjectDoc}" />
<materialDesign:PackIcon Kind="Link" />
</Hyperlink> </Hyperlink>
</TextBlock> </TextBlock>
<Button <Button
@@ -120,6 +121,7 @@
Style="{StaticResource ToolbarTextBlock}"> Style="{StaticResource ToolbarTextBlock}">
<Hyperlink Click="linkDnsSingboxObjectDoc_Click"> <Hyperlink Click="linkDnsSingboxObjectDoc_Click">
<TextBlock Text="{x:Static resx:ResUI.TbDnsSingboxObjectDoc}" /> <TextBlock Text="{x:Static resx:ResUI.TbDnsSingboxObjectDoc}" />
<materialDesign:PackIcon Kind="Link" />
</Hyperlink> </Hyperlink>
</TextBlock> </TextBlock>
<Button <Button

View File

@@ -4,6 +4,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:conv="clr-namespace:v2rayN.Converters" xmlns:conv="clr-namespace:v2rayN.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:reactiveui="http://reactiveui.net" xmlns:reactiveui="http://reactiveui.net"
xmlns:resx="clr-namespace:v2rayN.Resx" xmlns:resx="clr-namespace:v2rayN.Resx"
@@ -83,6 +84,7 @@
Style="{StaticResource ToolbarTextBlock}"> Style="{StaticResource ToolbarTextBlock}">
<Hyperlink Click="linkRuleobjectDoc_Click"> <Hyperlink Click="linkRuleobjectDoc_Click">
<TextBlock Text="{x:Static resx:ResUI.TbRuleobjectDoc}" /> <TextBlock Text="{x:Static resx:ResUI.TbRuleobjectDoc}" />
<materialDesign:PackIcon Kind="Link" />
</Hyperlink> </Hyperlink>
</TextBlock> </TextBlock>

View File

@@ -114,17 +114,36 @@
VerticalAlignment="Center" VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}" Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.LvRemarks}" /> Text="{x:Static resx:ResUI.LvRemarks}" />
<TextBox <StackPanel
x:Name="txtRemarks"
Grid.Row="0" Grid.Row="0"
Grid.Column="1" Grid.Column="1"
Width="400" Orientation="Horizontal">
Margin="4"
HorizontalAlignment="Left" <TextBox
VerticalAlignment="Top" x:Name="txtRemarks"
AcceptsReturn="True" Grid.Row="0"
Style="{StaticResource DefTextBox}" Grid.Column="1"
TextWrapping="Wrap" /> Width="300"
Margin="4"
HorizontalAlignment="Left"
VerticalAlignment="Top"
AcceptsReturn="True"
Style="{StaticResource DefTextBox}"
TextWrapping="Wrap" />
<TextBlock
Margin="4"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.LvSort}" />
<TextBox
x:Name="txtSort"
Width="100"
Margin="4"
HorizontalAlignment="Left"
AcceptsReturn="True"
Style="{StaticResource DefTextBox}" />
</StackPanel>
<TextBlock <TextBlock
Grid.Row="1" Grid.Row="1"
@@ -190,11 +209,11 @@
Style="{StaticResource DefTextBox}" Style="{StaticResource DefTextBox}"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
<Button <Button
x:Name="btnBrowse" x:Name="btnBrowseCustomIcon"
Grid.Row="3" Grid.Row="3"
Grid.Column="2" Grid.Column="2"
Margin="2,0,8,0" Margin="2,0,8,0"
Click="btnBrowse_Click" Click="btnBrowseCustomIcon_Click"
Content="{x:Static resx:ResUI.TbBrowse}" Content="{x:Static resx:ResUI.TbBrowse}"
Style="{StaticResource DefButton}" /> Style="{StaticResource DefButton}" />
@@ -203,17 +222,30 @@
Grid.Column="0" Grid.Column="0"
Margin="4" Margin="4"
VerticalAlignment="Center" VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}" Style="{StaticResource ToolbarTextBlock}">
Text="{x:Static resx:ResUI.LvSort}" /> <Hyperlink Click="linkCustomRulesetPath4Singbox">
<TextBlock Text="{x:Static resx:ResUI.LvCustomRulesetPath4Singbox}" />
<materialDesign:PackIcon Kind="Link" />
</Hyperlink>
</TextBlock>
<TextBox <TextBox
x:Name="txtSort" x:Name="txtCustomRulesetPath4Singbox"
Grid.Row="4" Grid.Row="4"
Grid.Column="1" Grid.Column="1"
Width="200" Width="600"
Margin="4" Margin="4"
HorizontalAlignment="Left" VerticalAlignment="Top"
AcceptsReturn="True" AcceptsReturn="True"
Style="{StaticResource DefTextBox}" /> Style="{StaticResource DefTextBox}"
TextWrapping="Wrap" />
<Button
x:Name="btnBrowseCustomRulesetPath4Singbox"
Grid.Row="4"
Grid.Column="2"
Margin="2,0,8,0"
Click="btnBrowseCustomRulesetPath4Singbox_Click"
Content="{x:Static resx:ResUI.TbBrowse}"
Style="{StaticResource DefButton}" />
</Grid> </Grid>
<TabControl x:Name="tabAdvanced"> <TabControl x:Name="tabAdvanced">

View File

@@ -51,6 +51,7 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.SelectedRouting.url, v => v.txtUrl.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedRouting.url, v => v.txtUrl.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedRouting.customIcon, v => v.txtCustomIcon.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedRouting.customIcon, v => v.txtCustomIcon.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedRouting.customRulesetPath4Singbox, v => v.txtCustomRulesetPath4Singbox.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedRouting.sort, v => v.txtSort.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedRouting.sort, v => v.txtSort.Text).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.RuleAddCmd, v => v.menuRuleAdd).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.RuleAddCmd, v => v.menuRuleAdd).DisposeWith(disposables);
@@ -128,7 +129,7 @@ namespace v2rayN.Views
lstRules.SelectAll(); lstRules.SelectAll();
} }
private void btnBrowse_Click(object sender, System.Windows.RoutedEventArgs e) private void btnBrowseCustomIcon_Click(object sender, System.Windows.RoutedEventArgs e)
{ {
if (UI.OpenFileDialog(out string fileName, if (UI.OpenFileDialog(out string fileName,
"PNG,ICO|*.png;*.ico") != true) "PNG,ICO|*.png;*.ico") != true)
@@ -138,5 +139,21 @@ namespace v2rayN.Views
txtCustomIcon.Text = fileName; txtCustomIcon.Text = fileName;
} }
private void btnBrowseCustomRulesetPath4Singbox_Click(object sender, RoutedEventArgs e)
{
if (UI.OpenFileDialog(out string fileName,
"Config|*.json|All|*.*") != true)
{
return;
}
txtCustomRulesetPath4Singbox.Text = fileName;
}
private void linkCustomRulesetPath4Singbox(object sender, RoutedEventArgs e)
{
Utils.ProcessStart("https://github.com/2dust/v2rayCustomRoutingList/blob/master/singbox_custom_ruleset_example.json");
}
} }
} }

View File

@@ -90,6 +90,7 @@
Style="{StaticResource ToolbarTextBlock}"> Style="{StaticResource ToolbarTextBlock}">
<Hyperlink Click="linkdomainStrategy_Click"> <Hyperlink Click="linkdomainStrategy_Click">
<TextBlock Text="{x:Static resx:ResUI.TbdomainStrategy}" /> <TextBlock Text="{x:Static resx:ResUI.TbdomainStrategy}" />
<materialDesign:PackIcon Kind="Link" />
</Hyperlink> </Hyperlink>
</TextBlock> </TextBlock>
<ComboBox <ComboBox
@@ -115,6 +116,7 @@
Style="{StaticResource ToolbarTextBlock}"> Style="{StaticResource ToolbarTextBlock}">
<Hyperlink Click="linkdomainStrategy4Singbox_Click"> <Hyperlink Click="linkdomainStrategy4Singbox_Click">
<TextBlock Text="{x:Static resx:ResUI.TbdomainStrategy4Singbox}" /> <TextBlock Text="{x:Static resx:ResUI.TbdomainStrategy4Singbox}" />
<materialDesign:PackIcon Kind="Link" />
</Hyperlink> </Hyperlink>
</TextBlock> </TextBlock>
<ComboBox <ComboBox

View File

@@ -170,17 +170,11 @@ JNIEXPORT void JNICALL Java_it_gui_yass_MainActivity_onNativeDestroy(JNIEnv* env
g_activity_obj = nullptr; g_activity_obj = nullptr;
} }
static uint64_t g_last_sync_time; static uint64_t g_last_sync_time = 0;
static uint64_t g_last_tx_bytes; static uint64_t g_last_tx_bytes = 0;
static uint64_t g_last_rx_bytes; static uint64_t g_last_rx_bytes = 0;
JNIEXPORT void JNICALL Java_it_gui_yass_MainActivity_nativeStart(JNIEnv* env, jobject obj) { JNIEXPORT void JNICALL Java_it_gui_yass_MainActivity_nativeStart(JNIEnv* env, jobject obj) {
g_last_sync_time = GetMonotonicTime();
g_last_tx_bytes = 0;
g_last_rx_bytes = 0;
cli::total_tx_bytes = 0;
cli::total_rx_bytes = 0;
g_worker->Start([&](asio::error_code ec) { g_worker->Start([&](asio::error_code ec) {
if (!ec) { if (!ec) {
config::SaveConfig(); config::SaveConfig();
@@ -204,8 +198,8 @@ JNIEXPORT jlongArray JNICALL Java_it_gui_yass_MainActivity_getRealtimeTransferRa
static uint64_t rx_rate = 0; static uint64_t rx_rate = 0;
static uint64_t tx_rate = 0; static uint64_t tx_rate = 0;
if (delta_time > NS_PER_SECOND) { if (delta_time > NS_PER_SECOND) {
uint64_t rx_bytes = cli::total_rx_bytes; uint64_t rx_bytes = net::cli::total_rx_bytes;
uint64_t tx_bytes = cli::total_tx_bytes; uint64_t tx_bytes = net::cli::total_tx_bytes;
rx_rate = static_cast<double>(rx_bytes - g_last_rx_bytes) / delta_time * NS_PER_SECOND; rx_rate = static_cast<double>(rx_bytes - g_last_rx_bytes) / delta_time * NS_PER_SECOND;
tx_rate = static_cast<double>(tx_bytes - g_last_tx_bytes) / delta_time * NS_PER_SECOND; tx_rate = static_cast<double>(tx_bytes - g_last_tx_bytes) / delta_time * NS_PER_SECOND;
g_last_sync_time = sync_time; g_last_sync_time = sync_time;

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