mirror of
https://github.com/bolucat/Archive.git
synced 2026-04-23 00:17:16 +08:00
Update On Thu Aug 14 20:41:00 CEST 2025
This commit is contained in:
@@ -1089,3 +1089,4 @@ Update On Sun Aug 10 20:40:02 CEST 2025
|
|||||||
Update On Mon Aug 11 20:43:53 CEST 2025
|
Update On Mon Aug 11 20:43:53 CEST 2025
|
||||||
Update On Tue Aug 12 20:40:42 CEST 2025
|
Update On Tue Aug 12 20:40:42 CEST 2025
|
||||||
Update On Wed Aug 13 20:43:46 CEST 2025
|
Update On Wed Aug 13 20:43:46 CEST 2025
|
||||||
|
Update On Thu Aug 14 20:40:52 CEST 2025
|
||||||
|
|||||||
@@ -5,58 +5,50 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
)
|
)
|
||||||
|
|
||||||
func DefaultValue[T any]() T {
|
|
||||||
var defaultValue T
|
|
||||||
return defaultValue
|
|
||||||
}
|
|
||||||
|
|
||||||
type TypedValue[T any] struct {
|
type TypedValue[T any] struct {
|
||||||
_ noCopy
|
value atomic.Pointer[T]
|
||||||
value atomic.Value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// tValue is a struct with determined type to resolve atomic.Value usages with interface types
|
func (t *TypedValue[T]) Load() (v T) {
|
||||||
// https://github.com/golang/go/issues/22550
|
v, _ = t.LoadOk()
|
||||||
//
|
return
|
||||||
// The intention to have an atomic value store for errors. However, running this code panics:
|
|
||||||
// panic: sync/atomic: store of inconsistently typed value into Value
|
|
||||||
// This is because atomic.Value requires that the underlying concrete type be the same (which is a reasonable expectation for its implementation).
|
|
||||||
// When going through the atomic.Value.Store method call, the fact that both these are of the error interface is lost.
|
|
||||||
type tValue[T any] struct {
|
|
||||||
value T
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TypedValue[T]) Load() T {
|
func (t *TypedValue[T]) LoadOk() (v T, ok bool) {
|
||||||
value, _ := t.LoadOk()
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *TypedValue[T]) LoadOk() (_ T, ok bool) {
|
|
||||||
value := t.value.Load()
|
value := t.value.Load()
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return DefaultValue[T](), false
|
return
|
||||||
}
|
}
|
||||||
return value.(tValue[T]).value, true
|
return *value, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TypedValue[T]) Store(value T) {
|
func (t *TypedValue[T]) Store(value T) {
|
||||||
t.value.Store(tValue[T]{value})
|
t.value.Store(&value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TypedValue[T]) Swap(new T) T {
|
func (t *TypedValue[T]) Swap(new T) (v T) {
|
||||||
old := t.value.Swap(tValue[T]{new})
|
old := t.value.Swap(&new)
|
||||||
if old == nil {
|
if old == nil {
|
||||||
return DefaultValue[T]()
|
return
|
||||||
}
|
}
|
||||||
return old.(tValue[T]).value
|
return *old
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TypedValue[T]) CompareAndSwap(old, new T) bool {
|
func (t *TypedValue[T]) CompareAndSwap(old, new T) bool {
|
||||||
return t.value.CompareAndSwap(tValue[T]{old}, tValue[T]{new}) ||
|
for {
|
||||||
// In the edge-case where [atomic.Value.Store] is uninitialized
|
currentP := t.value.Load()
|
||||||
// and trying to compare with the zero value of T,
|
var currentValue T
|
||||||
// then compare-and-swap with the nil any value.
|
if currentP != nil {
|
||||||
(any(old) == any(DefaultValue[T]()) && t.value.CompareAndSwap(any(nil), tValue[T]{new}))
|
currentValue = *currentP
|
||||||
|
}
|
||||||
|
// Compare old and current via runtime equality check.
|
||||||
|
if any(currentValue) != any(old) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if t.value.CompareAndSwap(currentP, &new) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TypedValue[T]) MarshalJSON() ([]byte, error) {
|
func (t *TypedValue[T]) MarshalJSON() ([]byte, error) {
|
||||||
@@ -89,9 +81,3 @@ func NewTypedValue[T any](t T) (v TypedValue[T]) {
|
|||||||
v.Store(t)
|
v.Store(t)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type noCopy struct{}
|
|
||||||
|
|
||||||
// Lock is a no-op used by -copylocks checker from `go vet`.
|
|
||||||
func (*noCopy) Lock() {}
|
|
||||||
func (*noCopy) Unlock() {}
|
|
||||||
|
|||||||
@@ -7,20 +7,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestTypedValue(t *testing.T) {
|
func TestTypedValue(t *testing.T) {
|
||||||
{
|
|
||||||
// Always wrapping should not allocate for simple values
|
|
||||||
// because tValue[T] has the same memory layout as T.
|
|
||||||
var v TypedValue[bool]
|
|
||||||
bools := []bool{true, false}
|
|
||||||
if n := int(testing.AllocsPerRun(1000, func() {
|
|
||||||
for _, b := range bools {
|
|
||||||
v.Store(b)
|
|
||||||
}
|
|
||||||
})); n != 0 {
|
|
||||||
t.Errorf("AllocsPerRun = %d, want 0", n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
var v TypedValue[int]
|
var v TypedValue[int]
|
||||||
got, gotOk := v.LoadOk()
|
got, gotOk := v.LoadOk()
|
||||||
@@ -58,20 +44,126 @@ func TestTypedValue(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
e1, e2, e3 := io.EOF, &os.PathError{}, &os.PathError{}
|
||||||
|
var v TypedValue[error]
|
||||||
|
if v.CompareAndSwap(e1, e2) != false {
|
||||||
|
t.Fatalf("CompareAndSwap = true, want false")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != nil {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, nil)
|
||||||
|
}
|
||||||
|
if v.CompareAndSwap(nil, e1) != true {
|
||||||
|
t.Fatalf("CompareAndSwap = false, want true")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != e1 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, e1)
|
||||||
|
}
|
||||||
|
if v.CompareAndSwap(e2, e3) != false {
|
||||||
|
t.Fatalf("CompareAndSwap = true, want false")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != e1 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, e1)
|
||||||
|
}
|
||||||
|
if v.CompareAndSwap(e1, e2) != true {
|
||||||
|
t.Fatalf("CompareAndSwap = false, want true")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != e2 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, e2)
|
||||||
|
}
|
||||||
|
if v.CompareAndSwap(e3, e2) != false {
|
||||||
|
t.Fatalf("CompareAndSwap = true, want false")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != e2 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, e2)
|
||||||
|
}
|
||||||
|
if v.CompareAndSwap(nil, e3) != false {
|
||||||
|
t.Fatalf("CompareAndSwap = true, want false")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != e2 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, e2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
c1, c2, c3 := make(chan struct{}), make(chan struct{}), make(chan struct{})
|
c1, c2, c3 := make(chan struct{}), make(chan struct{}), make(chan struct{})
|
||||||
var v TypedValue[chan struct{}]
|
var v TypedValue[chan struct{}]
|
||||||
if v.CompareAndSwap(c1, c2) != false {
|
if v.CompareAndSwap(c1, c2) != false {
|
||||||
t.Fatalf("CompareAndSwap = true, want false")
|
t.Fatalf("CompareAndSwap = true, want false")
|
||||||
}
|
}
|
||||||
|
if value := v.Load(); value != nil {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, nil)
|
||||||
|
}
|
||||||
if v.CompareAndSwap(nil, c1) != true {
|
if v.CompareAndSwap(nil, c1) != true {
|
||||||
t.Fatalf("CompareAndSwap = false, want true")
|
t.Fatalf("CompareAndSwap = false, want true")
|
||||||
}
|
}
|
||||||
|
if value := v.Load(); value != c1 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, c1)
|
||||||
|
}
|
||||||
if v.CompareAndSwap(c2, c3) != false {
|
if v.CompareAndSwap(c2, c3) != false {
|
||||||
t.Fatalf("CompareAndSwap = true, want false")
|
t.Fatalf("CompareAndSwap = true, want false")
|
||||||
}
|
}
|
||||||
|
if value := v.Load(); value != c1 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, c1)
|
||||||
|
}
|
||||||
if v.CompareAndSwap(c1, c2) != true {
|
if v.CompareAndSwap(c1, c2) != true {
|
||||||
t.Fatalf("CompareAndSwap = false, want true")
|
t.Fatalf("CompareAndSwap = false, want true")
|
||||||
}
|
}
|
||||||
|
if value := v.Load(); value != c2 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, c2)
|
||||||
|
}
|
||||||
|
if v.CompareAndSwap(c3, c2) != false {
|
||||||
|
t.Fatalf("CompareAndSwap = true, want false")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != c2 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, c2)
|
||||||
|
}
|
||||||
|
if v.CompareAndSwap(nil, c3) != false {
|
||||||
|
t.Fatalf("CompareAndSwap = true, want false")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != c2 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, c2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
c1, c2, c3 := &io.LimitedReader{}, &io.SectionReader{}, &io.SectionReader{}
|
||||||
|
var v TypedValue[io.Reader]
|
||||||
|
if v.CompareAndSwap(c1, c2) != false {
|
||||||
|
t.Fatalf("CompareAndSwap = true, want false")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != nil {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, nil)
|
||||||
|
}
|
||||||
|
if v.CompareAndSwap(nil, c1) != true {
|
||||||
|
t.Fatalf("CompareAndSwap = false, want true")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != c1 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, c1)
|
||||||
|
}
|
||||||
|
if v.CompareAndSwap(c2, c3) != false {
|
||||||
|
t.Fatalf("CompareAndSwap = true, want false")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != c1 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, c1)
|
||||||
|
}
|
||||||
|
if v.CompareAndSwap(c1, c2) != true {
|
||||||
|
t.Fatalf("CompareAndSwap = false, want true")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != c2 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, c2)
|
||||||
|
}
|
||||||
|
if v.CompareAndSwap(c3, c2) != false {
|
||||||
|
t.Fatalf("CompareAndSwap = true, want false")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != c2 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, c2)
|
||||||
|
}
|
||||||
|
if v.CompareAndSwap(nil, c3) != false {
|
||||||
|
t.Fatalf("CompareAndSwap = true, want false")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != c2 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, c2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,27 +10,27 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
keepAliveIdle = atomic.NewTypedValue[time.Duration](0 * time.Second)
|
keepAliveIdle = atomic.NewInt64(0)
|
||||||
keepAliveInterval = atomic.NewTypedValue[time.Duration](0 * time.Second)
|
keepAliveInterval = atomic.NewInt64(0)
|
||||||
disableKeepAlive = atomic.NewBool(false)
|
disableKeepAlive = atomic.NewBool(false)
|
||||||
|
|
||||||
SetDisableKeepAliveCallback = utils.NewCallback[bool]()
|
SetDisableKeepAliveCallback = utils.NewCallback[bool]()
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetKeepAliveIdle(t time.Duration) {
|
func SetKeepAliveIdle(t time.Duration) {
|
||||||
keepAliveIdle.Store(t)
|
keepAliveIdle.Store(int64(t))
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetKeepAliveInterval(t time.Duration) {
|
func SetKeepAliveInterval(t time.Duration) {
|
||||||
keepAliveInterval.Store(t)
|
keepAliveInterval.Store(int64(t))
|
||||||
}
|
}
|
||||||
|
|
||||||
func KeepAliveIdle() time.Duration {
|
func KeepAliveIdle() time.Duration {
|
||||||
return keepAliveIdle.Load()
|
return time.Duration(keepAliveIdle.Load())
|
||||||
}
|
}
|
||||||
|
|
||||||
func KeepAliveInterval() time.Duration {
|
func KeepAliveInterval() time.Duration {
|
||||||
return keepAliveInterval.Load()
|
return time.Duration(keepAliveInterval.Load())
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetDisableKeepAlive(disable bool) {
|
func SetDisableKeepAlive(disable bool) {
|
||||||
|
|||||||
+7
-7
@@ -3,7 +3,6 @@ module github.com/metacubex/mihomo
|
|||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/3andne/restls-client-go v0.1.6
|
|
||||||
github.com/bahlo/generic-list-go v0.2.0
|
github.com/bahlo/generic-list-go v0.2.0
|
||||||
github.com/coreos/go-iptables v0.8.0
|
github.com/coreos/go-iptables v0.8.0
|
||||||
github.com/dlclark/regexp2 v1.11.5
|
github.com/dlclark/regexp2 v1.11.5
|
||||||
@@ -19,18 +18,20 @@ require (
|
|||||||
github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab
|
github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab
|
||||||
github.com/metacubex/bart v0.20.5
|
github.com/metacubex/bart v0.20.5
|
||||||
github.com/metacubex/bbolt v0.0.0-20250725135710-010dbbbb7a5b
|
github.com/metacubex/bbolt v0.0.0-20250725135710-010dbbbb7a5b
|
||||||
|
github.com/metacubex/blake3 v0.1.0
|
||||||
github.com/metacubex/chacha v0.1.5
|
github.com/metacubex/chacha v0.1.5
|
||||||
github.com/metacubex/fswatch v0.1.1
|
github.com/metacubex/fswatch v0.1.1
|
||||||
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759
|
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759
|
||||||
github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295
|
github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295
|
||||||
github.com/metacubex/randv2 v0.2.0
|
github.com/metacubex/randv2 v0.2.0
|
||||||
github.com/metacubex/sing v0.5.4
|
github.com/metacubex/restls-client-go v0.1.7
|
||||||
|
github.com/metacubex/sing v0.5.5
|
||||||
github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac
|
github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac
|
||||||
github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb
|
github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb
|
||||||
github.com/metacubex/sing-shadowsocks v0.2.11
|
github.com/metacubex/sing-shadowsocks v0.2.12
|
||||||
github.com/metacubex/sing-shadowsocks2 v0.2.5
|
github.com/metacubex/sing-shadowsocks2 v0.2.6
|
||||||
github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2
|
github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2
|
||||||
github.com/metacubex/sing-tun v0.4.7-0.20250801130030-308b828865ae
|
github.com/metacubex/sing-tun v0.4.7
|
||||||
github.com/metacubex/sing-vmess v0.2.4-0.20250731011226-ea28d589924d
|
github.com/metacubex/sing-vmess v0.2.4-0.20250731011226-ea28d589924d
|
||||||
github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f
|
github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f
|
||||||
github.com/metacubex/smux v0.0.0-20250503055512-501391591dee
|
github.com/metacubex/smux v0.0.0-20250503055512-501391591dee
|
||||||
@@ -59,7 +60,6 @@ require (
|
|||||||
golang.org/x/sys v0.30.0 // lastest version compatible with golang1.20
|
golang.org/x/sys v0.30.0 // lastest version compatible with golang1.20
|
||||||
google.golang.org/protobuf v1.34.2 // lastest version compatible with golang1.20
|
google.golang.org/protobuf v1.34.2 // lastest version compatible with golang1.20
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
lukechampine.com/blake3 v1.3.0 // lastest version compatible with golang1.20
|
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -85,11 +85,11 @@ require (
|
|||||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||||
github.com/hashicorp/yamux v0.1.2 // indirect
|
github.com/hashicorp/yamux v0.1.2 // indirect
|
||||||
github.com/josharian/native v1.1.0 // indirect
|
github.com/josharian/native v1.1.0 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
|
||||||
github.com/kr/text v0.2.0 // indirect
|
github.com/kr/text v0.2.0 // indirect
|
||||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
github.com/mdlayher/socket v0.4.1 // indirect
|
github.com/mdlayher/socket v0.4.1 // indirect
|
||||||
|
github.com/metacubex/ascon v0.1.0 // indirect
|
||||||
github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b // indirect
|
github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b // indirect
|
||||||
github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 // indirect
|
github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 // indirect
|
||||||
github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect
|
github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect
|
||||||
|
|||||||
+14
-14
@@ -1,5 +1,3 @@
|
|||||||
github.com/3andne/restls-client-go v0.1.6 h1:tRx/YilqW7iHpgmEL4E1D8dAsuB0tFF3uvncS+B6I08=
|
|
||||||
github.com/3andne/restls-client-go v0.1.6/go.mod h1:iEdTZNt9kzPIxjIGSMScUFSBrUH6bFRNg0BWlP4orEY=
|
|
||||||
github.com/RyuaNerin/go-krypto v1.3.0 h1:smavTzSMAx8iuVlGb4pEwl9MD2qicqMzuXR2QWp2/Pg=
|
github.com/RyuaNerin/go-krypto v1.3.0 h1:smavTzSMAx8iuVlGb4pEwl9MD2qicqMzuXR2QWp2/Pg=
|
||||||
github.com/RyuaNerin/go-krypto v1.3.0/go.mod h1:9R9TU936laAIqAmjcHo/LsaXYOZlymudOAxjaBf62UM=
|
github.com/RyuaNerin/go-krypto v1.3.0/go.mod h1:9R9TU936laAIqAmjcHo/LsaXYOZlymudOAxjaBf62UM=
|
||||||
github.com/RyuaNerin/testingutil v0.1.0 h1:IYT6JL57RV3U2ml3dLHZsVtPOP6yNK7WUVdzzlpNrss=
|
github.com/RyuaNerin/testingutil v0.1.0 h1:IYT6JL57RV3U2ml3dLHZsVtPOP6yNK7WUVdzzlpNrss=
|
||||||
@@ -81,8 +79,6 @@ github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtL
|
|||||||
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||||
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||||
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
|
|
||||||
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
|
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
@@ -98,10 +94,14 @@ github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U
|
|||||||
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
|
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
|
||||||
github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab h1:Chbw+/31UC14YFNr78pESt5Vowlc62zziw05JCUqoL4=
|
github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab h1:Chbw+/31UC14YFNr78pESt5Vowlc62zziw05JCUqoL4=
|
||||||
github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab/go.mod h1:xVKK8jC5Sd3hfh7WjmCq+HorehIbrBijaUWmcuKjPcI=
|
github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab/go.mod h1:xVKK8jC5Sd3hfh7WjmCq+HorehIbrBijaUWmcuKjPcI=
|
||||||
|
github.com/metacubex/ascon v0.1.0 h1:6ZWxmXYszT1XXtwkf6nxfFhc/OTtQ9R3Vyj1jN32lGM=
|
||||||
|
github.com/metacubex/ascon v0.1.0/go.mod h1:eV5oim4cVPPdEL8/EYaTZ0iIKARH9pnhAK/fcT5Kacc=
|
||||||
github.com/metacubex/bart v0.20.5 h1:XkgLZ17QxfxkqKdGsojoM2Zu01mmHyyQSFzt2/calTM=
|
github.com/metacubex/bart v0.20.5 h1:XkgLZ17QxfxkqKdGsojoM2Zu01mmHyyQSFzt2/calTM=
|
||||||
github.com/metacubex/bart v0.20.5/go.mod h1:DCcyfP4MC+Zy7sLK7XeGuMw+P5K9mIRsYOBgiE8icsI=
|
github.com/metacubex/bart v0.20.5/go.mod h1:DCcyfP4MC+Zy7sLK7XeGuMw+P5K9mIRsYOBgiE8icsI=
|
||||||
github.com/metacubex/bbolt v0.0.0-20250725135710-010dbbbb7a5b h1:j7dadXD8I2KTmMt8jg1JcaP1ANL3JEObJPdANKcSYPY=
|
github.com/metacubex/bbolt v0.0.0-20250725135710-010dbbbb7a5b h1:j7dadXD8I2KTmMt8jg1JcaP1ANL3JEObJPdANKcSYPY=
|
||||||
github.com/metacubex/bbolt v0.0.0-20250725135710-010dbbbb7a5b/go.mod h1:+WmP0VJZDkDszvpa83HzfUp6QzARl/IKkMorH4+nODw=
|
github.com/metacubex/bbolt v0.0.0-20250725135710-010dbbbb7a5b/go.mod h1:+WmP0VJZDkDszvpa83HzfUp6QzARl/IKkMorH4+nODw=
|
||||||
|
github.com/metacubex/blake3 v0.1.0 h1:KGnjh/56REO7U+cgZA8dnBhxdP7jByrG7hTP+bu6cqY=
|
||||||
|
github.com/metacubex/blake3 v0.1.0/go.mod h1:CCkLdzFrqf7xmxCdhQFvJsRRV2mwOLDoSPg6vUTB9Uk=
|
||||||
github.com/metacubex/chacha v0.1.5 h1:fKWMb/5c7ZrY8Uoqi79PPFxl+qwR7X/q0OrsAubyX2M=
|
github.com/metacubex/chacha v0.1.5 h1:fKWMb/5c7ZrY8Uoqi79PPFxl+qwR7X/q0OrsAubyX2M=
|
||||||
github.com/metacubex/chacha v0.1.5/go.mod h1:Djn9bPZxLTXbJFSeyo0/qzEzQI+gUSSzttuzZM75GH8=
|
github.com/metacubex/chacha v0.1.5/go.mod h1:Djn9bPZxLTXbJFSeyo0/qzEzQI+gUSSzttuzZM75GH8=
|
||||||
github.com/metacubex/fswatch v0.1.1 h1:jqU7C/v+g0qc2RUFgmAOPoVvfl2BXXUXEumn6oQuxhU=
|
github.com/metacubex/fswatch v0.1.1 h1:jqU7C/v+g0qc2RUFgmAOPoVvfl2BXXUXEumn6oQuxhU=
|
||||||
@@ -116,21 +116,23 @@ github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295 h1:8JVlYuE8uS
|
|||||||
github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295/go.mod h1:1lktQFtCD17FZliVypbrDHwbsFSsmz2xz2TRXydvB5c=
|
github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295/go.mod h1:1lktQFtCD17FZliVypbrDHwbsFSsmz2xz2TRXydvB5c=
|
||||||
github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs=
|
github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs=
|
||||||
github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY=
|
github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY=
|
||||||
|
github.com/metacubex/restls-client-go v0.1.7 h1:eCwiXCTQb5WJu9IlgYvDBA1OgrINv58dEe7hcN5H15k=
|
||||||
|
github.com/metacubex/restls-client-go v0.1.7/go.mod h1:BN/U52vPw7j8VTSh2vleD/MnmVKCov84mS5VcjVHH4g=
|
||||||
github.com/metacubex/sing v0.5.2/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w=
|
github.com/metacubex/sing v0.5.2/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w=
|
||||||
github.com/metacubex/sing v0.5.4 h1:a4kAOZmF+OXosbzPEcrSc5QD35/ex+MNuZsrcuWskHk=
|
github.com/metacubex/sing v0.5.5 h1:m5U8iHvRAUxlme3FZlE/LPIGHjU8oMCUzXWGbQQAC1E=
|
||||||
github.com/metacubex/sing v0.5.4/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w=
|
github.com/metacubex/sing v0.5.5/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w=
|
||||||
github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac h1:wDH/Jh/yqWbzPktqJP+Y1cUG8hchcrzKzUxJiSpnaQs=
|
github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac h1:wDH/Jh/yqWbzPktqJP+Y1cUG8hchcrzKzUxJiSpnaQs=
|
||||||
github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac/go.mod h1:3rt1soewn0O6j89GCLmwAQFsq257u0jf2zQSPhTL3Bw=
|
github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac/go.mod h1:3rt1soewn0O6j89GCLmwAQFsq257u0jf2zQSPhTL3Bw=
|
||||||
github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb h1:U/m3h8lp/j7i8zFgfvScLdZa1/Y8dd74oO7iZaQq80s=
|
github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb h1:U/m3h8lp/j7i8zFgfvScLdZa1/Y8dd74oO7iZaQq80s=
|
||||||
github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb/go.mod h1:B60FxaPHjR1SeQB0IiLrgwgvKsaoASfOWdiqhLjmMGA=
|
github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb/go.mod h1:B60FxaPHjR1SeQB0IiLrgwgvKsaoASfOWdiqhLjmMGA=
|
||||||
github.com/metacubex/sing-shadowsocks v0.2.11 h1:p2NGNOdF95e6XvdDKipLj1FRRqR8dnbfC/7pw2CCTlw=
|
github.com/metacubex/sing-shadowsocks v0.2.12 h1:Wqzo8bYXrK5aWqxu/TjlTnYZzAKtKsaFQBdr6IHFaBE=
|
||||||
github.com/metacubex/sing-shadowsocks v0.2.11/go.mod h1:bT1PCTV316zFnlToRMk5zt9HmIQYRBveiT71mplYPfc=
|
github.com/metacubex/sing-shadowsocks v0.2.12/go.mod h1:2e5EIaw0rxKrm1YTRmiMnDulwbGxH9hAFlrwQLQMQkU=
|
||||||
github.com/metacubex/sing-shadowsocks2 v0.2.5 h1:MnPn0hbcDkSJt6TlpI15XImHKK6IqaOwBUGPKyMnJnE=
|
github.com/metacubex/sing-shadowsocks2 v0.2.6 h1:ZR1kYT0f0Vi64iQSS09OdhFfppiNkh7kjgRdMm0SB98=
|
||||||
github.com/metacubex/sing-shadowsocks2 v0.2.5/go.mod h1:Zyh+rAQRyevYfG/COCvDs1c/YMhGqCuknn7QrGmoQIw=
|
github.com/metacubex/sing-shadowsocks2 v0.2.6/go.mod h1:vOEbfKC60txi0ca+yUlqEwOGc3Obl6cnSgx9Gf45KjE=
|
||||||
github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 h1:gXU+MYPm7Wme3/OAY2FFzVq9d9GxPHOqu5AQfg/ddhI=
|
github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 h1:gXU+MYPm7Wme3/OAY2FFzVq9d9GxPHOqu5AQfg/ddhI=
|
||||||
github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2/go.mod h1:mbfboaXauKJNIHJYxQRa+NJs4JU9NZfkA+I33dS2+9E=
|
github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2/go.mod h1:mbfboaXauKJNIHJYxQRa+NJs4JU9NZfkA+I33dS2+9E=
|
||||||
github.com/metacubex/sing-tun v0.4.7-0.20250801130030-308b828865ae h1:hKYGuBaJBLqNmySrYrOGDXXsyxXNaR8omO96QDsRI2s=
|
github.com/metacubex/sing-tun v0.4.7 h1:ZDY/W+1c7PeWWKeKRyUo18fySF/TWjB0i5ui81Ar778=
|
||||||
github.com/metacubex/sing-tun v0.4.7-0.20250801130030-308b828865ae/go.mod h1:2YywXPWW8Z97kTH7RffOeykKzU+l0aiKlglWV1PAS64=
|
github.com/metacubex/sing-tun v0.4.7/go.mod h1:xHecZRwBnKWe6zG9amAK9cXf91lF6blgjBqm+VvOrmU=
|
||||||
github.com/metacubex/sing-vmess v0.2.4-0.20250731011226-ea28d589924d h1:koSVAQiYqU/qtJ527e+wbsEPvTaM39HW75LSvh04IT0=
|
github.com/metacubex/sing-vmess v0.2.4-0.20250731011226-ea28d589924d h1:koSVAQiYqU/qtJ527e+wbsEPvTaM39HW75LSvh04IT0=
|
||||||
github.com/metacubex/sing-vmess v0.2.4-0.20250731011226-ea28d589924d/go.mod h1:21R5R1u90uUvBQF0owoooEu96/SAYYD56nDrwm6nFaM=
|
github.com/metacubex/sing-vmess v0.2.4-0.20250731011226-ea28d589924d/go.mod h1:21R5R1u90uUvBQF0owoooEu96/SAYYD56nDrwm6nFaM=
|
||||||
github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f h1:Sr/DYKYofKHKc4GF3qkRGNuj6XA6c0eqPgEDN+VAsYU=
|
github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f h1:Sr/DYKYofKHKc4GF3qkRGNuj6XA6c0eqPgEDN+VAsYU=
|
||||||
@@ -279,5 +281,3 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33
|
|||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE=
|
|
||||||
lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
tls "github.com/3andne/restls-client-go"
|
tls "github.com/metacubex/restls-client-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import (
|
|||||||
"net/netip"
|
"net/netip"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/metacubex/blake3"
|
||||||
"github.com/metacubex/quic-go"
|
"github.com/metacubex/quic-go"
|
||||||
"lukechampine.com/blake3"
|
|
||||||
|
|
||||||
C "github.com/metacubex/mihomo/constant"
|
C "github.com/metacubex/mihomo/constant"
|
||||||
"github.com/metacubex/mihomo/transport/socks5"
|
"github.com/metacubex/mihomo/transport/socks5"
|
||||||
|
|||||||
@@ -105,26 +105,20 @@ func (vc *Conn) sendRequest(p []byte) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var buffer *buf.Buffer
|
requestLen := 1 // protocol version
|
||||||
if vc.IsXTLSVisionEnabled() {
|
requestLen += 16 // UUID
|
||||||
buffer = buf.New()
|
requestLen += 1 // addons length
|
||||||
defer buffer.Release()
|
requestLen += len(addonsBytes)
|
||||||
} else {
|
requestLen += 1 // command
|
||||||
requestLen := 1 // protocol version
|
if !vc.dst.Mux {
|
||||||
requestLen += 16 // UUID
|
requestLen += 2 // port
|
||||||
requestLen += 1 // addons length
|
requestLen += 1 // addr type
|
||||||
requestLen += len(addonsBytes)
|
requestLen += len(vc.dst.Addr)
|
||||||
requestLen += 1 // command
|
|
||||||
if !vc.dst.Mux {
|
|
||||||
requestLen += 2 // port
|
|
||||||
requestLen += 1 // addr type
|
|
||||||
requestLen += len(vc.dst.Addr)
|
|
||||||
}
|
|
||||||
requestLen += len(p)
|
|
||||||
|
|
||||||
buffer = buf.NewSize(requestLen)
|
|
||||||
defer buffer.Release()
|
|
||||||
}
|
}
|
||||||
|
requestLen += len(p)
|
||||||
|
|
||||||
|
buffer := buf.NewSize(requestLen)
|
||||||
|
defer buffer.Release()
|
||||||
|
|
||||||
buf.Must(
|
buf.Must(
|
||||||
buffer.WriteByte(Version), // protocol version
|
buffer.WriteByte(Version), // protocol version
|
||||||
@@ -182,10 +176,6 @@ func (vc *Conn) NeedHandshake() bool {
|
|||||||
return vc.needHandshake
|
return vc.needHandshake
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vc *Conn) IsXTLSVisionEnabled() bool {
|
|
||||||
return vc.addons != nil && vc.addons.Flow == XRV
|
|
||||||
}
|
|
||||||
|
|
||||||
// newConn return a Conn instance
|
// newConn return a Conn instance
|
||||||
func newConn(conn net.Conn, client *Client, dst *DstAddr) (net.Conn, error) {
|
func newConn(conn net.Conn, client *Client, dst *DstAddr) (net.Conn, error) {
|
||||||
c := &Conn{
|
c := &Conn{
|
||||||
|
|||||||
@@ -4,11 +4,13 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"crypto/sha256"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -36,13 +38,12 @@ func init() {
|
|||||||
|
|
||||||
type ClientInstance struct {
|
type ClientInstance struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
nfsEKey *mlkem.EncapsulationKey768
|
nfsEKey *mlkem.EncapsulationKey768
|
||||||
nfsEKeyBytes []byte
|
xorKey []byte
|
||||||
xor uint32
|
minutes time.Duration
|
||||||
minutes time.Duration
|
expire time.Time
|
||||||
expire time.Time
|
baseKey []byte
|
||||||
baseKey []byte
|
ticket []byte
|
||||||
ticket []byte
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClientConn struct {
|
type ClientConn struct {
|
||||||
@@ -59,10 +60,17 @@ type ClientConn struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *ClientInstance) Init(nfsEKeyBytes []byte, xor uint32, minutes time.Duration) (err error) {
|
func (i *ClientInstance) Init(nfsEKeyBytes []byte, xor uint32, minutes time.Duration) (err error) {
|
||||||
|
if i.nfsEKey != nil {
|
||||||
|
err = errors.New("already initialized")
|
||||||
|
return
|
||||||
|
}
|
||||||
i.nfsEKey, err = mlkem.NewEncapsulationKey768(nfsEKeyBytes)
|
i.nfsEKey, err = mlkem.NewEncapsulationKey768(nfsEKeyBytes)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
if xor > 0 {
|
if xor > 0 {
|
||||||
i.nfsEKeyBytes = nfsEKeyBytes
|
xorKey := sha256.Sum256(nfsEKeyBytes)
|
||||||
i.xor = xor
|
i.xorKey = xorKey[:]
|
||||||
}
|
}
|
||||||
i.minutes = minutes
|
i.minutes = minutes
|
||||||
return
|
return
|
||||||
@@ -72,8 +80,8 @@ func (i *ClientInstance) Handshake(conn net.Conn) (net.Conn, error) {
|
|||||||
if i.nfsEKey == nil {
|
if i.nfsEKey == nil {
|
||||||
return nil, errors.New("uninitialized")
|
return nil, errors.New("uninitialized")
|
||||||
}
|
}
|
||||||
if i.xor > 0 {
|
if i.xorKey != nil {
|
||||||
conn = NewXorConn(conn, i.nfsEKeyBytes)
|
conn = NewXorConn(conn, i.xorKey)
|
||||||
}
|
}
|
||||||
c := &ClientConn{Conn: conn}
|
c := &ClientConn{Conn: conn}
|
||||||
|
|
||||||
@@ -107,16 +115,16 @@ func (i *ClientInstance) Handshake(conn net.Conn) (net.Conn, error) {
|
|||||||
if _, err := c.Conn.Write(clientHello); err != nil {
|
if _, err := c.Conn.Write(clientHello); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// client can send more padding / NFS AEAD messages if needed
|
// client can send more paddings / NFS AEAD messages if needed
|
||||||
|
|
||||||
_, t, l, err := ReadAndDecodeHeader(c.Conn)
|
_, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before server hello
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if t != 1 {
|
if t != 1 {
|
||||||
return nil, fmt.Errorf("unexpected type %v, expect random hello", t)
|
return nil, fmt.Errorf("unexpected type %v, expect random hello", t)
|
||||||
}
|
}
|
||||||
|
|
||||||
peerRandomHello := make([]byte, 1088+21)
|
peerRandomHello := make([]byte, 1088+21)
|
||||||
if l != len(peerRandomHello) {
|
if l != len(peerRandomHello) {
|
||||||
return nil, fmt.Errorf("unexpected length %v for random hello", l)
|
return nil, fmt.Errorf("unexpected length %v for random hello", l)
|
||||||
@@ -193,27 +201,9 @@ func (c *ClientConn) Read(b []byte) (int, error) {
|
|||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
if c.peerAead == nil {
|
if c.peerAead == nil {
|
||||||
var t byte
|
_, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before random hello
|
||||||
var l int
|
if err != nil {
|
||||||
var err error
|
if c.instance != nil && strings.HasPrefix(err.Error(), "invalid header: ") { // 0-RTT's 0-RTT
|
||||||
if c.instance == nil { // from 1-RTT
|
|
||||||
for {
|
|
||||||
if _, t, l, err = ReadAndDecodeHeader(c.Conn); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
if t != 23 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if _, err := io.ReadFull(c.Conn, make([]byte, l)); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
h := make([]byte, 5)
|
|
||||||
if _, err := io.ReadFull(c.Conn, h); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
if t, l, err = DecodeHeader(h); err != nil {
|
|
||||||
c.instance.Lock()
|
c.instance.Lock()
|
||||||
if bytes.Equal(c.ticket, c.instance.ticket) {
|
if bytes.Equal(c.ticket, c.instance.ticket) {
|
||||||
c.instance.expire = time.Now() // expired
|
c.instance.expire = time.Now() // expired
|
||||||
@@ -221,6 +211,7 @@ func (c *ClientConn) Read(b []byte) (int, error) {
|
|||||||
c.instance.Unlock()
|
c.instance.Unlock()
|
||||||
return 0, errors.New("new handshake needed")
|
return 0, errors.New("new handshake needed")
|
||||||
}
|
}
|
||||||
|
return 0, err
|
||||||
}
|
}
|
||||||
if t != 0 {
|
if t != 0 {
|
||||||
return 0, fmt.Errorf("unexpected type %v, expect server random", t)
|
return 0, fmt.Errorf("unexpected type %v, expect server random", t)
|
||||||
|
|||||||
@@ -45,10 +45,10 @@ func DecodeHeader(h []byte) (t byte, l int, err error) {
|
|||||||
} else if h[0] == 1 && h[1] == 1 && h[2] == 1 {
|
} else if h[0] == 1 && h[1] == 1 && h[2] == 1 {
|
||||||
t = 1
|
t = 1
|
||||||
} else {
|
} else {
|
||||||
h = nil
|
l = 0
|
||||||
}
|
}
|
||||||
if h == nil || l < 17 || l > 17000 { // TODO: TLSv1.3 max length
|
if l < 17 || l > 17000 { // TODO: TLSv1.3 max length
|
||||||
err = fmt.Errorf("invalid header: %v", h[:5])
|
err = fmt.Errorf("invalid header: %v", h[:5]) // DO NOT CHANGE: relied by client's Read()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -62,6 +62,17 @@ func ReadAndDecodeHeader(conn net.Conn) (h []byte, t byte, l int, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ReadAndDiscardPaddings(conn net.Conn) (h []byte, t byte, l int, err error) {
|
||||||
|
for {
|
||||||
|
if h, t, l, err = ReadAndDecodeHeader(conn); err != nil || t != 23 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err = io.ReadFull(conn, make([]byte, l)); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func NewAead(c byte, secret, salt, info []byte) (aead cipher.AEAD) {
|
func NewAead(c byte, secret, salt, info []byte) (aead cipher.AEAD) {
|
||||||
key := make([]byte, 32)
|
key := make([]byte, 32)
|
||||||
hkdf.New(sha256.New, secret, salt, info).Read(key)
|
hkdf.New(sha256.New, secret, salt, info).Read(key)
|
||||||
|
|||||||
@@ -9,4 +9,6 @@
|
|||||||
// https://github.com/XTLS/Xray-core/commit/1720be168fa069332c418503d30341fc6e01df7f
|
// https://github.com/XTLS/Xray-core/commit/1720be168fa069332c418503d30341fc6e01df7f
|
||||||
// https://github.com/XTLS/Xray-core/commit/0fd7691d6b28e05922d7a5a9313d97745a51ea63
|
// https://github.com/XTLS/Xray-core/commit/0fd7691d6b28e05922d7a5a9313d97745a51ea63
|
||||||
// https://github.com/XTLS/Xray-core/commit/09cc92c61d9067e0d65c1cae9124664ecfc78f43
|
// https://github.com/XTLS/Xray-core/commit/09cc92c61d9067e0d65c1cae9124664ecfc78f43
|
||||||
|
// https://github.com/XTLS/Xray-core/commit/2807ee432a1fbeb301815647189eacd650b12a8b
|
||||||
|
// https://github.com/XTLS/Xray-core/commit/bfe4820f2f086daf639b1957eb23dc13c843cad1
|
||||||
package encryption
|
package encryption
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"crypto/sha256"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@@ -23,12 +24,11 @@ type ServerSession struct {
|
|||||||
|
|
||||||
type ServerInstance struct {
|
type ServerInstance struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
nfsDKey *mlkem.DecapsulationKey768
|
nfsDKey *mlkem.DecapsulationKey768
|
||||||
nfsEKeyBytes []byte
|
xorKey []byte
|
||||||
xor uint32
|
minutes time.Duration
|
||||||
minutes time.Duration
|
sessions map[[21]byte]*ServerSession
|
||||||
sessions map[[21]byte]*ServerSession
|
closed bool
|
||||||
closed bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServerConn struct {
|
type ServerConn struct {
|
||||||
@@ -45,10 +45,17 @@ type ServerConn struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *ServerInstance) Init(nfsDKeySeed []byte, xor uint32, minutes time.Duration) (err error) {
|
func (i *ServerInstance) Init(nfsDKeySeed []byte, xor uint32, minutes time.Duration) (err error) {
|
||||||
|
if i.nfsDKey != nil {
|
||||||
|
err = errors.New("already initialized")
|
||||||
|
return
|
||||||
|
}
|
||||||
i.nfsDKey, err = mlkem.NewDecapsulationKey768(nfsDKeySeed)
|
i.nfsDKey, err = mlkem.NewDecapsulationKey768(nfsDKeySeed)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
if xor > 0 {
|
if xor > 0 {
|
||||||
i.nfsEKeyBytes = i.nfsDKey.EncapsulationKey().Bytes()
|
xorKey := sha256.Sum256(i.nfsDKey.EncapsulationKey().Bytes())
|
||||||
i.xor = xor
|
i.xorKey = xorKey[:]
|
||||||
}
|
}
|
||||||
if minutes > 0 {
|
if minutes > 0 {
|
||||||
i.minutes = minutes
|
i.minutes = minutes
|
||||||
@@ -85,18 +92,15 @@ func (i *ServerInstance) Handshake(conn net.Conn) (net.Conn, error) {
|
|||||||
if i.nfsDKey == nil {
|
if i.nfsDKey == nil {
|
||||||
return nil, errors.New("uninitialized")
|
return nil, errors.New("uninitialized")
|
||||||
}
|
}
|
||||||
if i.xor > 0 {
|
if i.xorKey != nil {
|
||||||
conn = NewXorConn(conn, i.nfsEKeyBytes)
|
conn = NewXorConn(conn, i.xorKey)
|
||||||
}
|
}
|
||||||
c := &ServerConn{Conn: conn}
|
c := &ServerConn{Conn: conn}
|
||||||
|
|
||||||
_, t, l, err := ReadAndDecodeHeader(c.Conn)
|
_, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before client/ticket hello
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if t == 23 {
|
|
||||||
return nil, errors.New("unexpected data")
|
|
||||||
}
|
|
||||||
|
|
||||||
if t == 0 {
|
if t == 0 {
|
||||||
if i.minutes == 0 {
|
if i.minutes == 0 {
|
||||||
@@ -113,9 +117,13 @@ func (i *ServerInstance) Handshake(conn net.Conn) (net.Conn, error) {
|
|||||||
s := i.sessions[[21]byte(peerTicketHello)]
|
s := i.sessions[[21]byte(peerTicketHello)]
|
||||||
i.RUnlock()
|
i.RUnlock()
|
||||||
if s == nil {
|
if s == nil {
|
||||||
noise := make([]byte, randBetween(100, 1000))
|
noises := make([]byte, randBetween(100, 1000))
|
||||||
rand.Read(noise)
|
var err error
|
||||||
c.Conn.Write(noise) // make client do new handshake
|
for err == nil {
|
||||||
|
rand.Read(noises)
|
||||||
|
_, _, err = DecodeHeader(noises)
|
||||||
|
}
|
||||||
|
c.Conn.Write(noises) // make client do new handshake
|
||||||
return nil, errors.New("expired ticket")
|
return nil, errors.New("expired ticket")
|
||||||
}
|
}
|
||||||
if _, replay := s.randoms.LoadOrStore([32]byte(peerTicketHello[21:]), true); replay {
|
if _, replay := s.randoms.LoadOrStore([32]byte(peerTicketHello[21:]), true); replay {
|
||||||
@@ -165,7 +173,7 @@ func (i *ServerInstance) Handshake(conn net.Conn) (net.Conn, error) {
|
|||||||
if _, err := c.Conn.Write(serverHello); err != nil {
|
if _, err := c.Conn.Write(serverHello); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// server can send more padding / PFS AEAD messages if needed
|
// server can send more paddings / PFS AEAD messages if needed
|
||||||
|
|
||||||
if i.minutes > 0 {
|
if i.minutes > 0 {
|
||||||
i.Lock()
|
i.Lock()
|
||||||
@@ -185,20 +193,10 @@ func (c *ServerConn) Read(b []byte) (int, error) {
|
|||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
if c.peerAead == nil {
|
if c.peerAead == nil {
|
||||||
if c.peerRandom == nil { // from 1-RTT
|
if c.peerRandom == nil { // 1-RTT's 0-RTT
|
||||||
var t byte
|
_, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before ticket hello
|
||||||
var l int
|
if err != nil {
|
||||||
var err error
|
return 0, err
|
||||||
for {
|
|
||||||
if _, t, l, err = ReadAndDecodeHeader(c.Conn); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
if t != 23 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if _, err := io.ReadFull(c.Conn, make([]byte, l)); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if t != 0 {
|
if t != 0 {
|
||||||
return 0, fmt.Errorf("unexpected type %v, expect ticket hello", t)
|
return 0, fmt.Errorf("unexpected type %v, expect ticket hello", t)
|
||||||
|
|||||||
@@ -18,11 +18,11 @@ type XorConn struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewXorConn(conn net.Conn, key []byte) *XorConn {
|
func NewXorConn(conn net.Conn, key []byte) *XorConn {
|
||||||
return &XorConn{Conn: conn, key: key[:16]}
|
return &XorConn{Conn: conn, key: key}
|
||||||
//chacha20.NewUnauthenticatedCipher()
|
//chacha20.NewUnauthenticatedCipher()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *XorConn) Write(b []byte) (int, error) { // two records at most
|
func (c *XorConn) Write(b []byte) (int, error) { // whole one/two records
|
||||||
if len(b) == 0 {
|
if len(b) == 0 {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
@@ -34,10 +34,10 @@ func (c *XorConn) Write(b []byte) (int, error) { // two records at most
|
|||||||
c.ctr = cipher.NewCTR(block, iv)
|
c.ctr = cipher.NewCTR(block, iv)
|
||||||
}
|
}
|
||||||
t, l, _ := DecodeHeader(b)
|
t, l, _ := DecodeHeader(b)
|
||||||
if t != 23 {
|
if t == 23 { // single 23
|
||||||
l += 10 // 5+l+5
|
|
||||||
} else {
|
|
||||||
l = 5
|
l = 5
|
||||||
|
} else { // 1/0 + 23, or noises only
|
||||||
|
l += 10
|
||||||
}
|
}
|
||||||
c.ctr.XORKeyStream(b[:l], b[:l]) // caller MUST discard b
|
c.ctr.XORKeyStream(b[:l], b[:l]) // caller MUST discard b
|
||||||
if iv != nil {
|
if iv != nil {
|
||||||
@@ -73,8 +73,8 @@ func (c *XorConn) Read(b []byte) (int, error) { // 5-bytes, data, 5-bytes...
|
|||||||
return len(b), nil
|
return len(b), nil
|
||||||
}
|
}
|
||||||
c.peerCtr.XORKeyStream(b, b)
|
c.peerCtr.XORKeyStream(b, b)
|
||||||
if c.isHeader {
|
if c.isHeader { // always 5-bytes
|
||||||
if t, _, _ := DecodeHeader(b); t == 23 { // always 5-bytes
|
if t, _, _ := DecodeHeader(b); t == 23 {
|
||||||
c.skipNext = true
|
c.skipNext = true
|
||||||
} else {
|
} else {
|
||||||
c.isHeader = false
|
c.isHeader = false
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package vision
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
gotls "crypto/tls"
|
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -12,7 +11,6 @@ import (
|
|||||||
|
|
||||||
"github.com/metacubex/mihomo/common/buf"
|
"github.com/metacubex/mihomo/common/buf"
|
||||||
N "github.com/metacubex/mihomo/common/net"
|
N "github.com/metacubex/mihomo/common/net"
|
||||||
tlsC "github.com/metacubex/mihomo/component/tls"
|
|
||||||
"github.com/metacubex/mihomo/log"
|
"github.com/metacubex/mihomo/log"
|
||||||
|
|
||||||
"github.com/gofrs/uuid/v5"
|
"github.com/gofrs/uuid/v5"
|
||||||
@@ -181,17 +179,10 @@ func (vc *Conn) WriteBuffer(buffer *buf.Buffer) (err error) {
|
|||||||
buffer.Release()
|
buffer.Release()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
switch underlying := vc.tlsConn.(type) {
|
err = vc.checkTLSVersion()
|
||||||
case *gotls.Conn:
|
if err != nil {
|
||||||
if underlying.ConnectionState().Version != gotls.VersionTLS13 {
|
buffer.Release()
|
||||||
buffer.Release()
|
return err
|
||||||
return ErrNotTLS13
|
|
||||||
}
|
|
||||||
case *tlsC.UConn:
|
|
||||||
if underlying.ConnectionState().Version != tlsC.VersionTLS13 {
|
|
||||||
buffer.Release()
|
|
||||||
return ErrNotTLS13
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
vc.tlsConn = nil
|
vc.tlsConn = nil
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -67,3 +67,21 @@ func NewConn(conn connWithUpstream, userUUID *uuid.UUID) (*Conn, error) {
|
|||||||
c.rawInput = (*bytes.Buffer)(unsafe.Add(p, r.Offset))
|
c.rawInput = (*bytes.Buffer)(unsafe.Add(p, r.Offset))
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (vc *Conn) checkTLSVersion() error {
|
||||||
|
switch underlying := vc.tlsConn.(type) {
|
||||||
|
case *gotls.Conn:
|
||||||
|
if underlying.ConnectionState().Version != gotls.VersionTLS13 {
|
||||||
|
return ErrNotTLS13
|
||||||
|
}
|
||||||
|
case *tlsC.Conn:
|
||||||
|
if underlying.ConnectionState().Version != tlsC.VersionTLS13 {
|
||||||
|
return ErrNotTLS13
|
||||||
|
}
|
||||||
|
case *tlsC.UConn:
|
||||||
|
if underlying.ConnectionState().Version != tlsC.VersionTLS13 {
|
||||||
|
return ErrNotTLS13
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -56,12 +56,12 @@
|
|||||||
"@csstools/normalize.css": "12.1.1",
|
"@csstools/normalize.css": "12.1.1",
|
||||||
"@emotion/babel-plugin": "11.13.5",
|
"@emotion/babel-plugin": "11.13.5",
|
||||||
"@emotion/react": "11.14.0",
|
"@emotion/react": "11.14.0",
|
||||||
"@iconify/json": "2.2.371",
|
"@iconify/json": "2.2.373",
|
||||||
"@monaco-editor/react": "4.7.0",
|
"@monaco-editor/react": "4.7.0",
|
||||||
"@tanstack/react-query": "5.84.2",
|
"@tanstack/react-query": "5.84.2",
|
||||||
"@tanstack/react-router": "1.131.5",
|
"@tanstack/react-router": "1.131.10",
|
||||||
"@tanstack/react-router-devtools": "1.131.5",
|
"@tanstack/react-router-devtools": "1.131.10",
|
||||||
"@tanstack/router-plugin": "1.131.5",
|
"@tanstack/router-plugin": "1.131.11",
|
||||||
"@tauri-apps/plugin-clipboard-manager": "2.3.0",
|
"@tauri-apps/plugin-clipboard-manager": "2.3.0",
|
||||||
"@tauri-apps/plugin-dialog": "2.3.0",
|
"@tauri-apps/plugin-dialog": "2.3.0",
|
||||||
"@tauri-apps/plugin-fs": "2.4.0",
|
"@tauri-apps/plugin-fs": "2.4.0",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"manifest_version": 1,
|
"manifest_version": 1,
|
||||||
"latest": {
|
"latest": {
|
||||||
"mihomo": "v1.19.12",
|
"mihomo": "v1.19.12",
|
||||||
"mihomo_alpha": "alpha-0e9102d",
|
"mihomo_alpha": "alpha-0408da2",
|
||||||
"clash_rs": "v0.8.2",
|
"clash_rs": "v0.8.2",
|
||||||
"clash_premium": "2023-09-05-gdcc8d87",
|
"clash_premium": "2023-09-05-gdcc8d87",
|
||||||
"clash_rs_alpha": "0.8.2-alpha+sha.df9f591"
|
"clash_rs_alpha": "0.8.2-alpha+sha.df9f591"
|
||||||
@@ -69,5 +69,5 @@
|
|||||||
"linux-armv7hf": "clash-armv7-unknown-linux-gnueabihf"
|
"linux-armv7hf": "clash-armv7-unknown-linux-gnueabihf"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"updated_at": "2025-08-12T22:21:09.244Z"
|
"updated_at": "2025-08-13T22:21:26.184Z"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,7 +105,7 @@
|
|||||||
"stylelint-order": "7.0.0",
|
"stylelint-order": "7.0.0",
|
||||||
"stylelint-scss": "6.12.1",
|
"stylelint-scss": "6.12.1",
|
||||||
"tailwindcss": "4.1.11",
|
"tailwindcss": "4.1.11",
|
||||||
"tsx": "4.20.3",
|
"tsx": "4.20.4",
|
||||||
"typescript": "5.9.2",
|
"typescript": "5.9.2",
|
||||||
"typescript-eslint": "8.39.1"
|
"typescript-eslint": "8.39.1"
|
||||||
},
|
},
|
||||||
|
|||||||
Generated
+81
-88
@@ -164,8 +164,8 @@ importers:
|
|||||||
specifier: 4.1.11
|
specifier: 4.1.11
|
||||||
version: 4.1.11
|
version: 4.1.11
|
||||||
tsx:
|
tsx:
|
||||||
specifier: 4.20.3
|
specifier: 4.20.4
|
||||||
version: 4.20.3
|
version: 4.20.4
|
||||||
typescript:
|
typescript:
|
||||||
specifier: 5.9.2
|
specifier: 5.9.2
|
||||||
version: 5.9.2
|
version: 5.9.2
|
||||||
@@ -250,7 +250,7 @@ importers:
|
|||||||
version: 4.1.11
|
version: 4.1.11
|
||||||
'@tanstack/router-zod-adapter':
|
'@tanstack/router-zod-adapter':
|
||||||
specifier: 1.81.5
|
specifier: 1.81.5
|
||||||
version: 1.81.5(@tanstack/react-router@1.131.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(zod@4.0.17)
|
version: 1.81.5(@tanstack/react-router@1.131.10(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(zod@4.0.17)
|
||||||
'@tauri-apps/api':
|
'@tauri-apps/api':
|
||||||
specifier: 2.6.0
|
specifier: 2.6.0
|
||||||
version: 2.6.0
|
version: 2.6.0
|
||||||
@@ -343,8 +343,8 @@ importers:
|
|||||||
specifier: 11.14.0
|
specifier: 11.14.0
|
||||||
version: 11.14.0(@types/react@19.1.10)(react@19.1.1)
|
version: 11.14.0(@types/react@19.1.10)(react@19.1.1)
|
||||||
'@iconify/json':
|
'@iconify/json':
|
||||||
specifier: 2.2.371
|
specifier: 2.2.373
|
||||||
version: 2.2.371
|
version: 2.2.373
|
||||||
'@monaco-editor/react':
|
'@monaco-editor/react':
|
||||||
specifier: 4.7.0
|
specifier: 4.7.0
|
||||||
version: 4.7.0(monaco-editor@0.52.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
|
version: 4.7.0(monaco-editor@0.52.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
|
||||||
@@ -352,14 +352,14 @@ importers:
|
|||||||
specifier: 5.84.2
|
specifier: 5.84.2
|
||||||
version: 5.84.2(react@19.1.1)
|
version: 5.84.2(react@19.1.1)
|
||||||
'@tanstack/react-router':
|
'@tanstack/react-router':
|
||||||
specifier: 1.131.5
|
specifier: 1.131.10
|
||||||
version: 1.131.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
|
version: 1.131.10(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
|
||||||
'@tanstack/react-router-devtools':
|
'@tanstack/react-router-devtools':
|
||||||
specifier: 1.131.5
|
specifier: 1.131.10
|
||||||
version: 1.131.5(@tanstack/react-router@1.131.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.131.5)(csstype@3.1.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.5)(tiny-invariant@1.3.3)
|
version: 1.131.10(@tanstack/react-router@1.131.10(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.131.7)(csstype@3.1.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.5)(tiny-invariant@1.3.3)
|
||||||
'@tanstack/router-plugin':
|
'@tanstack/router-plugin':
|
||||||
specifier: 1.131.5
|
specifier: 1.131.11
|
||||||
version: 1.131.5(@tanstack/react-router@1.131.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1))
|
version: 1.131.11(@tanstack/react-router@1.131.10(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1))
|
||||||
'@tauri-apps/plugin-clipboard-manager':
|
'@tauri-apps/plugin-clipboard-manager':
|
||||||
specifier: 2.3.0
|
specifier: 2.3.0
|
||||||
version: 2.3.0
|
version: 2.3.0
|
||||||
@@ -395,13 +395,13 @@ importers:
|
|||||||
version: 13.15.2
|
version: 13.15.2
|
||||||
'@vitejs/plugin-legacy':
|
'@vitejs/plugin-legacy':
|
||||||
specifier: 7.2.1
|
specifier: 7.2.1
|
||||||
version: 7.2.1(terser@5.36.0)(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1))
|
version: 7.2.1(terser@5.36.0)(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1))
|
||||||
'@vitejs/plugin-react':
|
'@vitejs/plugin-react':
|
||||||
specifier: 4.7.0
|
specifier: 4.7.0
|
||||||
version: 4.7.0(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1))
|
version: 4.7.0(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1))
|
||||||
'@vitejs/plugin-react-swc':
|
'@vitejs/plugin-react-swc':
|
||||||
specifier: 3.11.0
|
specifier: 3.11.0
|
||||||
version: 3.11.0(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1))
|
version: 3.11.0(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1))
|
||||||
change-case:
|
change-case:
|
||||||
specifier: 5.4.4
|
specifier: 5.4.4
|
||||||
version: 5.4.4
|
version: 5.4.4
|
||||||
@@ -440,19 +440,19 @@ importers:
|
|||||||
version: 13.15.15
|
version: 13.15.15
|
||||||
vite:
|
vite:
|
||||||
specifier: 7.1.1
|
specifier: 7.1.1
|
||||||
version: 7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1)
|
version: 7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1)
|
||||||
vite-plugin-html:
|
vite-plugin-html:
|
||||||
specifier: 3.2.2
|
specifier: 3.2.2
|
||||||
version: 3.2.2(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1))
|
version: 3.2.2(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1))
|
||||||
vite-plugin-sass-dts:
|
vite-plugin-sass-dts:
|
||||||
specifier: 1.3.31
|
specifier: 1.3.31
|
||||||
version: 1.3.31(postcss@8.5.6)(prettier@3.6.2)(sass-embedded@1.90.0)(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1))
|
version: 1.3.31(postcss@8.5.6)(prettier@3.6.2)(sass-embedded@1.90.0)(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1))
|
||||||
vite-plugin-svgr:
|
vite-plugin-svgr:
|
||||||
specifier: 4.3.0
|
specifier: 4.3.0
|
||||||
version: 4.3.0(rollup@4.46.2)(typescript@5.9.2)(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1))
|
version: 4.3.0(rollup@4.46.2)(typescript@5.9.2)(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1))
|
||||||
vite-tsconfig-paths:
|
vite-tsconfig-paths:
|
||||||
specifier: 5.1.4
|
specifier: 5.1.4
|
||||||
version: 5.1.4(typescript@5.9.2)(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1))
|
version: 5.1.4(typescript@5.9.2)(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1))
|
||||||
zod:
|
zod:
|
||||||
specifier: 4.0.17
|
specifier: 4.0.17
|
||||||
version: 4.0.17
|
version: 4.0.17
|
||||||
@@ -488,7 +488,7 @@ importers:
|
|||||||
version: 19.1.10
|
version: 19.1.10
|
||||||
'@vitejs/plugin-react':
|
'@vitejs/plugin-react':
|
||||||
specifier: 4.7.0
|
specifier: 4.7.0
|
||||||
version: 4.7.0(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1))
|
version: 4.7.0(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1))
|
||||||
ahooks:
|
ahooks:
|
||||||
specifier: 3.9.0
|
specifier: 3.9.0
|
||||||
version: 3.9.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
|
version: 3.9.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
|
||||||
@@ -518,10 +518,10 @@ importers:
|
|||||||
version: 4.1.11
|
version: 4.1.11
|
||||||
vite:
|
vite:
|
||||||
specifier: 7.1.1
|
specifier: 7.1.1
|
||||||
version: 7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1)
|
version: 7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1)
|
||||||
vite-tsconfig-paths:
|
vite-tsconfig-paths:
|
||||||
specifier: 5.1.4
|
specifier: 5.1.4
|
||||||
version: 5.1.4(typescript@5.9.2)(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1))
|
version: 5.1.4(typescript@5.9.2)(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1))
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@emotion/react':
|
'@emotion/react':
|
||||||
specifier: 11.14.0
|
specifier: 11.14.0
|
||||||
@@ -546,7 +546,7 @@ importers:
|
|||||||
version: 5.2.0(typescript@5.9.2)
|
version: 5.2.0(typescript@5.9.2)
|
||||||
vite-plugin-dts:
|
vite-plugin-dts:
|
||||||
specifier: 4.5.4
|
specifier: 4.5.4
|
||||||
version: 4.5.4(@types/node@22.17.1)(rollup@4.46.2)(typescript@5.9.2)(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1))
|
version: 4.5.4(@types/node@22.17.1)(rollup@4.46.2)(typescript@5.9.2)(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1))
|
||||||
|
|
||||||
scripts:
|
scripts:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -1759,8 +1759,8 @@ packages:
|
|||||||
prettier-plugin-ember-template-tag:
|
prettier-plugin-ember-template-tag:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@iconify/json@2.2.371':
|
'@iconify/json@2.2.373':
|
||||||
resolution: {integrity: sha512-dnamUrgw8aDWz4STJOkQqqCz6GB2s7SHGPIY84EVQmlVXzM7T1V7L/csdL7r9bkA3AHF80+OXhx7o4FXn5L8pQ==}
|
resolution: {integrity: sha512-ZgDwDLgbzf/nEyDoSdC75A1XA0L7Q4rfz0ZKGiq/ZWTztrlM7ASBvjKb6/dhs+gtvepnOc5CLUrBcDUYKZblLg==}
|
||||||
|
|
||||||
'@iconify/types@2.0.0':
|
'@iconify/types@2.0.0':
|
||||||
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
|
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
|
||||||
@@ -2945,16 +2945,16 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^18 || ^19
|
react: ^18 || ^19
|
||||||
|
|
||||||
'@tanstack/react-router-devtools@1.131.5':
|
'@tanstack/react-router-devtools@1.131.10':
|
||||||
resolution: {integrity: sha512-3LaEbWDYGnzw4J8DM7KX32qRslGrSt67Cg7uoAYReBfDlLpWVRnjpyG2fef7nHDqn5HaAuV0IbY1n6Duwp5IyQ==}
|
resolution: {integrity: sha512-D9DlyPTQt0bkM1YcTykB9yYAiw6GhsvhvzOuprO0xKz3lMXbyuaQ5QO1xBfzhL+2Wv5nlnCLu68Ra3skE8TQTA==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@tanstack/react-router': ^1.131.5
|
'@tanstack/react-router': ^1.131.10
|
||||||
react: '>=18.0.0 || >=19.0.0'
|
react: '>=18.0.0 || >=19.0.0'
|
||||||
react-dom: '>=18.0.0 || >=19.0.0'
|
react-dom: '>=18.0.0 || >=19.0.0'
|
||||||
|
|
||||||
'@tanstack/react-router@1.131.5':
|
'@tanstack/react-router@1.131.10':
|
||||||
resolution: {integrity: sha512-71suJGuCmrHN9PLLRUDB3CGnW5RNcEEfgfX616TOpKamHs977H8P4/75BgWPRWcLHCga/1kkA6c7bddCwZ35Fw==}
|
resolution: {integrity: sha512-RjfCgHEHChmW3icKjLQSRKWKCJyzVd8qQXW2jF+cil5XXFeKvyuqm3R92uRIF/ONUUJ8b/V9/ET4/+dH/U8FPA==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: '>=18.0.0 || >=19.0.0'
|
react: '>=18.0.0 || >=19.0.0'
|
||||||
@@ -2979,15 +2979,15 @@ packages:
|
|||||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||||
|
|
||||||
'@tanstack/router-core@1.131.5':
|
'@tanstack/router-core@1.131.7':
|
||||||
resolution: {integrity: sha512-XVfZdnKNQbWfkQ6G7I9ml2wHp98Wy7wgTboP5SfrJHfOE+kPeHeZRJqF/pp5oqLZ2feBJqsDDKNWo9323L7sWQ==}
|
resolution: {integrity: sha512-NpFfAG1muv4abrCij6sEtRrVzlU+xYpY30NAgquHNhMMMNIiN7djzsaGV+vCJdR4u5mi13+f0c3f+f9MdekY5A==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
'@tanstack/router-devtools-core@1.131.5':
|
'@tanstack/router-devtools-core@1.131.7':
|
||||||
resolution: {integrity: sha512-kH3cZz7UfnVQW9vMZJ/CAx15pu+iGkn10N4rRKBVWCEJZFPX3GZvYEwkeALHASsV0Io7yUvKDcWfPsc+UowyzQ==}
|
resolution: {integrity: sha512-1GHWILJr69Ej/c8UUMhT7Srx392FbsDqRrPhCWWtrjmYOv6Fdx3HdKDJt/YdJGBc8z6x+V7EE41j+LZggD+70Q==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@tanstack/router-core': ^1.131.5
|
'@tanstack/router-core': ^1.131.7
|
||||||
csstype: ^3.0.10
|
csstype: ^3.0.10
|
||||||
solid-js: '>=1.9.5'
|
solid-js: '>=1.9.5'
|
||||||
tiny-invariant: ^1.3.3
|
tiny-invariant: ^1.3.3
|
||||||
@@ -2995,16 +2995,16 @@ packages:
|
|||||||
csstype:
|
csstype:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@tanstack/router-generator@1.131.5':
|
'@tanstack/router-generator@1.131.7':
|
||||||
resolution: {integrity: sha512-5+/zyp/R9WN8tHNVIEYQZpRMzcsOrNH06HoPnPMiLiB9T4WsOLFJCcHdyso9ofGQq+hoxB4M9SUBXVBbJVWbSw==}
|
resolution: {integrity: sha512-djwY5O1LdJo300EOZiYog5RsjB1DYzFtgX6a3uOkAmii7LHX9k9mhFXx2KrI4dLHLQsnlKexV9QvU6cSTFmsag==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
'@tanstack/router-plugin@1.131.5':
|
'@tanstack/router-plugin@1.131.11':
|
||||||
resolution: {integrity: sha512-Px+GSijNv1cbSm74+U+kEbuSFsspL+/BakzytAJFdh2O4342G32tha1cMFMlzXbDd9SW1FaLWgu3VqNHjGIpOg==}
|
resolution: {integrity: sha512-cPDWynVPHpST2UcdEqUAmpqXh50IuSenTPZj7aDhUkw1q8Oeerv6ixYy6GTfH2JDdgQ2IgzJpPBIWkvJ+mOYHA==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@rsbuild/core': '>=1.0.2'
|
'@rsbuild/core': '>=1.0.2'
|
||||||
'@tanstack/react-router': ^1.131.5
|
'@tanstack/react-router': ^1.131.10
|
||||||
vite: '>=5.0.0 || >=6.0.0'
|
vite: '>=5.0.0 || >=6.0.0'
|
||||||
vite-plugin-solid: ^2.11.2
|
vite-plugin-solid: ^2.11.2
|
||||||
webpack: '>=5.92.0'
|
webpack: '>=5.92.0'
|
||||||
@@ -5282,9 +5282,6 @@ packages:
|
|||||||
get-tsconfig@4.10.1:
|
get-tsconfig@4.10.1:
|
||||||
resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==}
|
resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==}
|
||||||
|
|
||||||
get-tsconfig@4.8.1:
|
|
||||||
resolution: {integrity: sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==}
|
|
||||||
|
|
||||||
git-raw-commits@4.0.0:
|
git-raw-commits@4.0.0:
|
||||||
resolution: {integrity: sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==}
|
resolution: {integrity: sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==}
|
||||||
engines: {node: '>=16'}
|
engines: {node: '>=16'}
|
||||||
@@ -8037,8 +8034,8 @@ packages:
|
|||||||
tslib@2.8.1:
|
tslib@2.8.1:
|
||||||
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
|
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
|
||||||
|
|
||||||
tsx@4.20.3:
|
tsx@4.20.4:
|
||||||
resolution: {integrity: sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==}
|
resolution: {integrity: sha512-yyxBKfORQ7LuRt/BQKBXrpcq59ZvSW0XxwfjAt3w2/8PmdxaFzijtMhTawprSHhpzeM5BgU2hXHG3lklIERZXg==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
@@ -9970,7 +9967,7 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@iconify/json@2.2.371':
|
'@iconify/json@2.2.373':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@iconify/types': 2.0.0
|
'@iconify/types': 2.0.0
|
||||||
pathe: 1.1.2
|
pathe: 1.1.2
|
||||||
@@ -11057,10 +11054,10 @@ snapshots:
|
|||||||
'@tanstack/query-core': 5.83.1
|
'@tanstack/query-core': 5.83.1
|
||||||
react: 19.1.1
|
react: 19.1.1
|
||||||
|
|
||||||
'@tanstack/react-router-devtools@1.131.5(@tanstack/react-router@1.131.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.131.5)(csstype@3.1.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.5)(tiny-invariant@1.3.3)':
|
'@tanstack/react-router-devtools@1.131.10(@tanstack/react-router@1.131.10(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.131.7)(csstype@3.1.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.5)(tiny-invariant@1.3.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tanstack/react-router': 1.131.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
|
'@tanstack/react-router': 1.131.10(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
|
||||||
'@tanstack/router-devtools-core': 1.131.5(@tanstack/router-core@1.131.5)(csstype@3.1.3)(solid-js@1.9.5)(tiny-invariant@1.3.3)
|
'@tanstack/router-devtools-core': 1.131.7(@tanstack/router-core@1.131.7)(csstype@3.1.3)(solid-js@1.9.5)(tiny-invariant@1.3.3)
|
||||||
react: 19.1.1
|
react: 19.1.1
|
||||||
react-dom: 19.1.1(react@19.1.1)
|
react-dom: 19.1.1(react@19.1.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@@ -11069,11 +11066,11 @@ snapshots:
|
|||||||
- solid-js
|
- solid-js
|
||||||
- tiny-invariant
|
- tiny-invariant
|
||||||
|
|
||||||
'@tanstack/react-router@1.131.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1)':
|
'@tanstack/react-router@1.131.10(react-dom@19.1.1(react@19.1.1))(react@19.1.1)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tanstack/history': 1.131.2
|
'@tanstack/history': 1.131.2
|
||||||
'@tanstack/react-store': 0.7.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
|
'@tanstack/react-store': 0.7.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
|
||||||
'@tanstack/router-core': 1.131.5
|
'@tanstack/router-core': 1.131.7
|
||||||
isbot: 5.1.28
|
isbot: 5.1.28
|
||||||
react: 19.1.1
|
react: 19.1.1
|
||||||
react-dom: 19.1.1(react@19.1.1)
|
react-dom: 19.1.1(react@19.1.1)
|
||||||
@@ -11099,7 +11096,7 @@ snapshots:
|
|||||||
react: 19.1.1
|
react: 19.1.1
|
||||||
react-dom: 19.1.1(react@19.1.1)
|
react-dom: 19.1.1(react@19.1.1)
|
||||||
|
|
||||||
'@tanstack/router-core@1.131.5':
|
'@tanstack/router-core@1.131.7':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tanstack/history': 1.131.2
|
'@tanstack/history': 1.131.2
|
||||||
'@tanstack/store': 0.7.0
|
'@tanstack/store': 0.7.0
|
||||||
@@ -11109,9 +11106,9 @@ snapshots:
|
|||||||
tiny-invariant: 1.3.3
|
tiny-invariant: 1.3.3
|
||||||
tiny-warning: 1.0.3
|
tiny-warning: 1.0.3
|
||||||
|
|
||||||
'@tanstack/router-devtools-core@1.131.5(@tanstack/router-core@1.131.5)(csstype@3.1.3)(solid-js@1.9.5)(tiny-invariant@1.3.3)':
|
'@tanstack/router-devtools-core@1.131.7(@tanstack/router-core@1.131.7)(csstype@3.1.3)(solid-js@1.9.5)(tiny-invariant@1.3.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tanstack/router-core': 1.131.5
|
'@tanstack/router-core': 1.131.7
|
||||||
clsx: 2.1.1
|
clsx: 2.1.1
|
||||||
goober: 2.1.16(csstype@3.1.3)
|
goober: 2.1.16(csstype@3.1.3)
|
||||||
solid-js: 1.9.5
|
solid-js: 1.9.5
|
||||||
@@ -11119,20 +11116,20 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
csstype: 3.1.3
|
csstype: 3.1.3
|
||||||
|
|
||||||
'@tanstack/router-generator@1.131.5':
|
'@tanstack/router-generator@1.131.7':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tanstack/router-core': 1.131.5
|
'@tanstack/router-core': 1.131.7
|
||||||
'@tanstack/router-utils': 1.131.2
|
'@tanstack/router-utils': 1.131.2
|
||||||
'@tanstack/virtual-file-routes': 1.131.2
|
'@tanstack/virtual-file-routes': 1.131.2
|
||||||
prettier: 3.6.2
|
prettier: 3.6.2
|
||||||
recast: 0.23.11
|
recast: 0.23.11
|
||||||
source-map: 0.7.4
|
source-map: 0.7.4
|
||||||
tsx: 4.20.3
|
tsx: 4.20.4
|
||||||
zod: 3.25.76
|
zod: 3.25.76
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@tanstack/router-plugin@1.131.5(@tanstack/react-router@1.131.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1))':
|
'@tanstack/router-plugin@1.131.11(@tanstack/react-router@1.131.10(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.28.0
|
'@babel/core': 7.28.0
|
||||||
'@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0)
|
'@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0)
|
||||||
@@ -11140,8 +11137,8 @@ snapshots:
|
|||||||
'@babel/template': 7.27.2
|
'@babel/template': 7.27.2
|
||||||
'@babel/traverse': 7.28.0
|
'@babel/traverse': 7.28.0
|
||||||
'@babel/types': 7.28.1
|
'@babel/types': 7.28.1
|
||||||
'@tanstack/router-core': 1.131.5
|
'@tanstack/router-core': 1.131.7
|
||||||
'@tanstack/router-generator': 1.131.5
|
'@tanstack/router-generator': 1.131.7
|
||||||
'@tanstack/router-utils': 1.131.2
|
'@tanstack/router-utils': 1.131.2
|
||||||
'@tanstack/virtual-file-routes': 1.131.2
|
'@tanstack/virtual-file-routes': 1.131.2
|
||||||
babel-dead-code-elimination: 1.0.10
|
babel-dead-code-elimination: 1.0.10
|
||||||
@@ -11149,8 +11146,8 @@ snapshots:
|
|||||||
unplugin: 2.3.5
|
unplugin: 2.3.5
|
||||||
zod: 3.25.76
|
zod: 3.25.76
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@tanstack/react-router': 1.131.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
|
'@tanstack/react-router': 1.131.10(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
|
||||||
vite: 7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1)
|
vite: 7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@@ -11165,9 +11162,9 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@tanstack/router-zod-adapter@1.81.5(@tanstack/react-router@1.131.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(zod@4.0.17)':
|
'@tanstack/router-zod-adapter@1.81.5(@tanstack/react-router@1.131.10(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(zod@4.0.17)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tanstack/react-router': 1.131.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
|
'@tanstack/react-router': 1.131.10(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
|
||||||
zod: 4.0.17
|
zod: 4.0.17
|
||||||
|
|
||||||
'@tanstack/store@0.7.0': {}
|
'@tanstack/store@0.7.0': {}
|
||||||
@@ -11762,7 +11759,7 @@ snapshots:
|
|||||||
'@unrs/resolver-binding-win32-x64-msvc@1.10.1':
|
'@unrs/resolver-binding-win32-x64-msvc@1.10.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@vitejs/plugin-legacy@7.2.1(terser@5.36.0)(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1))':
|
'@vitejs/plugin-legacy@7.2.1(terser@5.36.0)(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.28.0
|
'@babel/core': 7.28.0
|
||||||
'@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.28.0)
|
'@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.28.0)
|
||||||
@@ -11777,19 +11774,19 @@ snapshots:
|
|||||||
regenerator-runtime: 0.14.1
|
regenerator-runtime: 0.14.1
|
||||||
systemjs: 6.15.1
|
systemjs: 6.15.1
|
||||||
terser: 5.36.0
|
terser: 5.36.0
|
||||||
vite: 7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1)
|
vite: 7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@vitejs/plugin-react-swc@3.11.0(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1))':
|
'@vitejs/plugin-react-swc@3.11.0(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@rolldown/pluginutils': 1.0.0-beta.27
|
'@rolldown/pluginutils': 1.0.0-beta.27
|
||||||
'@swc/core': 1.13.0
|
'@swc/core': 1.13.0
|
||||||
vite: 7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1)
|
vite: 7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@swc/helpers'
|
- '@swc/helpers'
|
||||||
|
|
||||||
'@vitejs/plugin-react@4.7.0(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1))':
|
'@vitejs/plugin-react@4.7.0(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.28.0
|
'@babel/core': 7.28.0
|
||||||
'@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.0)
|
'@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.0)
|
||||||
@@ -11797,7 +11794,7 @@ snapshots:
|
|||||||
'@rolldown/pluginutils': 1.0.0-beta.27
|
'@rolldown/pluginutils': 1.0.0-beta.27
|
||||||
'@types/babel__core': 7.20.5
|
'@types/babel__core': 7.20.5
|
||||||
react-refresh: 0.17.0
|
react-refresh: 0.17.0
|
||||||
vite: 7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1)
|
vite: 7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@@ -13834,10 +13831,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
resolve-pkg-maps: 1.0.0
|
resolve-pkg-maps: 1.0.0
|
||||||
|
|
||||||
get-tsconfig@4.8.1:
|
|
||||||
dependencies:
|
|
||||||
resolve-pkg-maps: 1.0.0
|
|
||||||
|
|
||||||
git-raw-commits@4.0.0:
|
git-raw-commits@4.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
dargs: 8.1.0
|
dargs: 8.1.0
|
||||||
@@ -16798,10 +16791,10 @@ snapshots:
|
|||||||
|
|
||||||
tslib@2.8.1: {}
|
tslib@2.8.1: {}
|
||||||
|
|
||||||
tsx@4.20.3:
|
tsx@4.20.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild: 0.25.0
|
esbuild: 0.25.0
|
||||||
get-tsconfig: 4.8.1
|
get-tsconfig: 4.10.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
|
|
||||||
@@ -17168,7 +17161,7 @@ snapshots:
|
|||||||
- rollup
|
- rollup
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
vite-plugin-dts@4.5.4(@types/node@22.17.1)(rollup@4.46.2)(typescript@5.9.2)(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1)):
|
vite-plugin-dts@4.5.4(@types/node@22.17.1)(rollup@4.46.2)(typescript@5.9.2)(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@microsoft/api-extractor': 7.51.0(@types/node@22.17.1)
|
'@microsoft/api-extractor': 7.51.0(@types/node@22.17.1)
|
||||||
'@rollup/pluginutils': 5.1.4(rollup@4.46.2)
|
'@rollup/pluginutils': 5.1.4(rollup@4.46.2)
|
||||||
@@ -17181,13 +17174,13 @@ snapshots:
|
|||||||
magic-string: 0.30.17
|
magic-string: 0.30.17
|
||||||
typescript: 5.9.2
|
typescript: 5.9.2
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
vite: 7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1)
|
vite: 7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@types/node'
|
- '@types/node'
|
||||||
- rollup
|
- rollup
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
vite-plugin-html@3.2.2(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1)):
|
vite-plugin-html@3.2.2(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@rollup/pluginutils': 4.2.1
|
'@rollup/pluginutils': 4.2.1
|
||||||
colorette: 2.0.20
|
colorette: 2.0.20
|
||||||
@@ -17201,39 +17194,39 @@ snapshots:
|
|||||||
html-minifier-terser: 6.1.0
|
html-minifier-terser: 6.1.0
|
||||||
node-html-parser: 5.4.2
|
node-html-parser: 5.4.2
|
||||||
pathe: 0.2.0
|
pathe: 0.2.0
|
||||||
vite: 7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1)
|
vite: 7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1)
|
||||||
|
|
||||||
vite-plugin-sass-dts@1.3.31(postcss@8.5.6)(prettier@3.6.2)(sass-embedded@1.90.0)(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1)):
|
vite-plugin-sass-dts@1.3.31(postcss@8.5.6)(prettier@3.6.2)(sass-embedded@1.90.0)(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
postcss: 8.5.6
|
postcss: 8.5.6
|
||||||
postcss-js: 4.0.1(postcss@8.5.6)
|
postcss-js: 4.0.1(postcss@8.5.6)
|
||||||
prettier: 3.6.2
|
prettier: 3.6.2
|
||||||
sass-embedded: 1.90.0
|
sass-embedded: 1.90.0
|
||||||
vite: 7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1)
|
vite: 7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1)
|
||||||
|
|
||||||
vite-plugin-svgr@4.3.0(rollup@4.46.2)(typescript@5.9.2)(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1)):
|
vite-plugin-svgr@4.3.0(rollup@4.46.2)(typescript@5.9.2)(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@rollup/pluginutils': 5.1.3(rollup@4.46.2)
|
'@rollup/pluginutils': 5.1.3(rollup@4.46.2)
|
||||||
'@svgr/core': 8.1.0(typescript@5.9.2)
|
'@svgr/core': 8.1.0(typescript@5.9.2)
|
||||||
'@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.9.2))
|
'@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.9.2))
|
||||||
vite: 7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1)
|
vite: 7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- rollup
|
- rollup
|
||||||
- supports-color
|
- supports-color
|
||||||
- typescript
|
- typescript
|
||||||
|
|
||||||
vite-tsconfig-paths@5.1.4(typescript@5.9.2)(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1)):
|
vite-tsconfig-paths@5.1.4(typescript@5.9.2)(vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.3.7
|
debug: 4.3.7
|
||||||
globrex: 0.1.2
|
globrex: 0.1.2
|
||||||
tsconfck: 3.0.3(typescript@5.9.2)
|
tsconfck: 3.0.3(typescript@5.9.2)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
vite: 7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1)
|
vite: 7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
- typescript
|
- typescript
|
||||||
|
|
||||||
vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.1):
|
vite@7.1.1(@types/node@22.17.1)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.4)(yaml@2.8.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild: 0.25.0
|
esbuild: 0.25.0
|
||||||
fdir: 6.4.6(picomatch@4.0.3)
|
fdir: 6.4.6(picomatch@4.0.3)
|
||||||
@@ -17251,7 +17244,7 @@ snapshots:
|
|||||||
sass-embedded: 1.90.0
|
sass-embedded: 1.90.0
|
||||||
stylus: 0.62.0
|
stylus: 0.62.0
|
||||||
terser: 5.36.0
|
terser: 5.36.0
|
||||||
tsx: 4.20.3
|
tsx: 4.20.4
|
||||||
yaml: 2.8.1
|
yaml: 2.8.1
|
||||||
|
|
||||||
void-elements@3.1.0: {}
|
void-elements@3.1.0: {}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -16,7 +16,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout codebase
|
- name: Checkout codebase
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,125 @@
|
|||||||
|
From 9989fcd49c52500a2bf1f6d49411690dec45d2dc Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= <marko.makela@iki.fi>
|
||||||
|
Date: Sat, 2 Aug 2025 12:47:08 +0300
|
||||||
|
Subject: [PATCH] clk: qcom: gcc-ipq6018: rework nss_port5 clock to multiple
|
||||||
|
conf
|
||||||
|
|
||||||
|
Rework nss_port5 to use the new multiple configuration implementation
|
||||||
|
and correctly fix the clocks for this port under some corner case.
|
||||||
|
|
||||||
|
In OpenWrt, this patch avoids intermittent dmesg errors of the form
|
||||||
|
nss_port5_rx_clk_src: rcg didn't update its configuration.
|
||||||
|
|
||||||
|
This is a mechanical, straightforward port of
|
||||||
|
commit e88f03230dc07aa3293b6aeb078bd27370bb2594
|
||||||
|
("clk: qcom: gcc-ipq8074: rework nss_port5/6 clock to multiple conf")
|
||||||
|
to gcc-ipq6018, with two conflicts resolved: different frequency of the
|
||||||
|
P_XO clock source, and only 5 Ethernet ports.
|
||||||
|
|
||||||
|
This was originally developed by JiaY-shi <shi05275@163.com>.
|
||||||
|
|
||||||
|
Link: https://lore.kernel.org/all/20231220221724.3822-4-ansuelsmth@gmail.com/
|
||||||
|
Signed-off-by: Marko Mäkelä <marko.makela@iki.fi>
|
||||||
|
Tested-by: Marko Mäkelä <marko.makela@iki.fi>
|
||||||
|
---
|
||||||
|
drivers/clk/qcom/gcc-ipq6018.c | 60 +++++++++++++++++++++-------------
|
||||||
|
1 file changed, 38 insertions(+), 22 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/clk/qcom/gcc-ipq6018.c
|
||||||
|
+++ b/drivers/clk/qcom/gcc-ipq6018.c
|
||||||
|
@@ -511,15 +511,23 @@ static struct clk_rcg2 apss_ahb_clk_src
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
-static const struct freq_tbl ftbl_nss_port5_rx_clk_src[] = {
|
||||||
|
- F(24000000, P_XO, 1, 0, 0),
|
||||||
|
- F(25000000, P_UNIPHY1_RX, 12.5, 0, 0),
|
||||||
|
- F(25000000, P_UNIPHY0_RX, 5, 0, 0),
|
||||||
|
- F(78125000, P_UNIPHY1_RX, 4, 0, 0),
|
||||||
|
- F(125000000, P_UNIPHY1_RX, 2.5, 0, 0),
|
||||||
|
- F(125000000, P_UNIPHY0_RX, 1, 0, 0),
|
||||||
|
- F(156250000, P_UNIPHY1_RX, 2, 0, 0),
|
||||||
|
- F(312500000, P_UNIPHY1_RX, 1, 0, 0),
|
||||||
|
+static const struct freq_conf ftbl_nss_port5_rx_clk_src_25[] = {
|
||||||
|
+ C(P_UNIPHY1_RX, 12.5, 0, 0),
|
||||||
|
+ C(P_UNIPHY0_RX, 5, 0, 0),
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static const struct freq_conf ftbl_nss_port5_rx_clk_src_125[] = {
|
||||||
|
+ C(P_UNIPHY1_RX, 2.5, 0, 0),
|
||||||
|
+ C(P_UNIPHY0_RX, 1, 0, 0),
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static const struct freq_multi_tbl ftbl_nss_port5_rx_clk_src[] = {
|
||||||
|
+ FMS(24000000, P_XO, 1, 0, 0),
|
||||||
|
+ FM(25000000, ftbl_nss_port5_rx_clk_src_25),
|
||||||
|
+ FMS(78125000, P_UNIPHY1_RX, 4, 0, 0),
|
||||||
|
+ FM(125000000, ftbl_nss_port5_rx_clk_src_125),
|
||||||
|
+ FMS(156250000, P_UNIPHY1_RX, 2, 0, 0),
|
||||||
|
+ FMS(312500000, P_UNIPHY1_RX, 1, 0, 0),
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -547,26 +555,34 @@ gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32
|
||||||
|
|
||||||
|
static struct clk_rcg2 nss_port5_rx_clk_src = {
|
||||||
|
.cmd_rcgr = 0x68060,
|
||||||
|
- .freq_tbl = ftbl_nss_port5_rx_clk_src,
|
||||||
|
+ .freq_multi_tbl = ftbl_nss_port5_rx_clk_src,
|
||||||
|
.hid_width = 5,
|
||||||
|
.parent_map = gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias_map,
|
||||||
|
.clkr.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "nss_port5_rx_clk_src",
|
||||||
|
.parent_data = gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias,
|
||||||
|
.num_parents = 7,
|
||||||
|
- .ops = &clk_rcg2_ops,
|
||||||
|
+ .ops = &clk_rcg2_fm_ops,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
-static const struct freq_tbl ftbl_nss_port5_tx_clk_src[] = {
|
||||||
|
- F(24000000, P_XO, 1, 0, 0),
|
||||||
|
- F(25000000, P_UNIPHY1_TX, 12.5, 0, 0),
|
||||||
|
- F(25000000, P_UNIPHY0_TX, 5, 0, 0),
|
||||||
|
- F(78125000, P_UNIPHY1_TX, 4, 0, 0),
|
||||||
|
- F(125000000, P_UNIPHY1_TX, 2.5, 0, 0),
|
||||||
|
- F(125000000, P_UNIPHY0_TX, 1, 0, 0),
|
||||||
|
- F(156250000, P_UNIPHY1_TX, 2, 0, 0),
|
||||||
|
- F(312500000, P_UNIPHY1_TX, 1, 0, 0),
|
||||||
|
+static const struct freq_conf ftbl_nss_port5_tx_clk_src_25[] = {
|
||||||
|
+ C(P_UNIPHY1_TX, 12.5, 0, 0),
|
||||||
|
+ C(P_UNIPHY0_TX, 5, 0, 0),
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static const struct freq_conf ftbl_nss_port5_tx_clk_src_125[] = {
|
||||||
|
+ C(P_UNIPHY1_TX, 2.5, 0, 0),
|
||||||
|
+ C(P_UNIPHY0_TX, 1, 0, 0),
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static const struct freq_multi_tbl ftbl_nss_port5_tx_clk_src[] = {
|
||||||
|
+ FMS(24000000, P_XO, 1, 0, 0),
|
||||||
|
+ FM(25000000, ftbl_nss_port5_tx_clk_src_25),
|
||||||
|
+ FMS(78125000, P_UNIPHY1_TX, 4, 0, 0),
|
||||||
|
+ FM(125000000, ftbl_nss_port5_tx_clk_src_125),
|
||||||
|
+ FMS(156250000, P_UNIPHY1_TX, 2, 0, 0),
|
||||||
|
+ FMS(312500000, P_UNIPHY1_TX, 1, 0, 0),
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -594,14 +610,14 @@ gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32
|
||||||
|
|
||||||
|
static struct clk_rcg2 nss_port5_tx_clk_src = {
|
||||||
|
.cmd_rcgr = 0x68068,
|
||||||
|
- .freq_tbl = ftbl_nss_port5_tx_clk_src,
|
||||||
|
+ .freq_multi_tbl = ftbl_nss_port5_tx_clk_src,
|
||||||
|
.hid_width = 5,
|
||||||
|
.parent_map = gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias_map,
|
||||||
|
.clkr.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "nss_port5_tx_clk_src",
|
||||||
|
.parent_data = gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias,
|
||||||
|
.num_parents = 7,
|
||||||
|
- .ops = &clk_rcg2_ops,
|
||||||
|
+ .ops = &clk_rcg2_fm_ops,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
+5
-5
@@ -28,7 +28,7 @@ Signed-off-by: Robert Marko <robimarko@gmail.com>
|
|||||||
{ .hw = &gpll0.clkr.hw },
|
{ .hw = &gpll0.clkr.hw },
|
||||||
{ .hw = &gpll4.clkr.hw },
|
{ .hw = &gpll4.clkr.hw },
|
||||||
{ .hw = &nss_crypto_pll.clkr.hw },
|
{ .hw = &nss_crypto_pll.clkr.hw },
|
||||||
@@ -526,12 +526,12 @@ static const struct freq_tbl ftbl_nss_po
|
@@ -534,12 +534,12 @@ static const struct freq_multi_tbl ftbl_
|
||||||
static const struct clk_parent_data
|
static const struct clk_parent_data
|
||||||
gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias[] = {
|
gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias[] = {
|
||||||
{ .fw_name = "xo" },
|
{ .fw_name = "xo" },
|
||||||
@@ -46,7 +46,7 @@ Signed-off-by: Robert Marko <robimarko@gmail.com>
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct parent_map
|
static const struct parent_map
|
||||||
@@ -573,12 +573,12 @@ static const struct freq_tbl ftbl_nss_po
|
@@ -589,12 +589,12 @@ static const struct freq_multi_tbl ftbl_
|
||||||
static const struct clk_parent_data
|
static const struct clk_parent_data
|
||||||
gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias[] = {
|
gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias[] = {
|
||||||
{ .fw_name = "xo" },
|
{ .fw_name = "xo" },
|
||||||
@@ -64,7 +64,7 @@ Signed-off-by: Robert Marko <robimarko@gmail.com>
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct parent_map
|
static const struct parent_map
|
||||||
@@ -714,10 +714,10 @@ static const struct freq_tbl ftbl_nss_po
|
@@ -730,10 +730,10 @@ static const struct freq_tbl ftbl_nss_po
|
||||||
|
|
||||||
static const struct clk_parent_data gcc_xo_uniphy0_rx_tx_ubi32_bias[] = {
|
static const struct clk_parent_data gcc_xo_uniphy0_rx_tx_ubi32_bias[] = {
|
||||||
{ .fw_name = "xo" },
|
{ .fw_name = "xo" },
|
||||||
@@ -78,7 +78,7 @@ Signed-off-by: Robert Marko <robimarko@gmail.com>
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct parent_map gcc_xo_uniphy0_rx_tx_ubi32_bias_map[] = {
|
static const struct parent_map gcc_xo_uniphy0_rx_tx_ubi32_bias_map[] = {
|
||||||
@@ -750,10 +750,10 @@ static const struct freq_tbl ftbl_nss_po
|
@@ -766,10 +766,10 @@ static const struct freq_tbl ftbl_nss_po
|
||||||
|
|
||||||
static const struct clk_parent_data gcc_xo_uniphy0_tx_rx_ubi32_bias[] = {
|
static const struct clk_parent_data gcc_xo_uniphy0_tx_rx_ubi32_bias[] = {
|
||||||
{ .fw_name = "xo" },
|
{ .fw_name = "xo" },
|
||||||
@@ -92,7 +92,7 @@ Signed-off-by: Robert Marko <robimarko@gmail.com>
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct parent_map gcc_xo_uniphy0_tx_rx_ubi32_bias_map[] = {
|
static const struct parent_map gcc_xo_uniphy0_tx_rx_ubi32_bias_map[] = {
|
||||||
@@ -1899,12 +1899,11 @@ static const struct freq_tbl ftbl_ubi32_
|
@@ -1915,12 +1915,11 @@ static const struct freq_tbl ftbl_ubi32_
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ An example of client configuration is as follows.
|
|||||||
"multiplexing": {
|
"multiplexing": {
|
||||||
"level": "MULTIPLEXING_HIGH"
|
"level": "MULTIPLEXING_HIGH"
|
||||||
},
|
},
|
||||||
"handshakeMode": "HANDSHAKE_NO_WAIT"
|
"handshakeMode": "HANDSHAKE_STANDARD"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"activeProfile": "default",
|
"activeProfile": "default",
|
||||||
@@ -69,7 +69,7 @@ Please use a text editor to modify the following fields.
|
|||||||
5. Fill in `profiles` -> `servers` -> `portBindings` -> `port` with the TCP or UDP port number that mita is listening to. The port number must be the same as the one set in the proxy server. If you want to listen to a range of consecutive port numbers, you can also use the `portRange` property instead.
|
5. Fill in `profiles` -> `servers` -> `portBindings` -> `port` with the TCP or UDP port number that mita is listening to. The port number must be the same as the one set in the proxy server. If you want to listen to a range of consecutive port numbers, you can also use the `portRange` property instead.
|
||||||
6. [Optional] Specify a value between 1280 and 1400 for the `profiles` -> `mtu` property. The default value is 1400. This value must be the same as proxy server.
|
6. [Optional] Specify a value between 1280 and 1400 for the `profiles` -> `mtu` property. The default value is 1400. This value must be the same as proxy server.
|
||||||
7. [Optional] If you want to adjust the frequency of multiplexing, you can set a value for the `profiles` -> `multiplexing` -> `level` property. The values you can use here include `MULTIPLEXING_OFF`, `MULTIPLEXING_LOW`, `MULTIPLEXING_MIDDLE`, and `MULTIPLEXING_HIGH`. `MULTIPLEXING_OFF` will disable multiplexing. The default value is `MULTIPLEXING_LOW`.
|
7. [Optional] If you want to adjust the frequency of multiplexing, you can set a value for the `profiles` -> `multiplexing` -> `level` property. The values you can use here include `MULTIPLEXING_OFF`, `MULTIPLEXING_LOW`, `MULTIPLEXING_MIDDLE`, and `MULTIPLEXING_HIGH`. `MULTIPLEXING_OFF` will disable multiplexing. The default value is `MULTIPLEXING_LOW`.
|
||||||
8. [Optional] If you want to enable 0-RTT handshake, you can set the value of `profiles` -> `handshakeMode` property to `HANDSHAKE_NO_WAIT`, otherwise set it to `HANDSHAKE_STANDARD`. The default value is `HANDSHAKE_STANDARD`.
|
8. [Optional] If you want to enable 0-RTT handshake (experimental feature), you can set the value of `profiles` -> `handshakeMode` property to `HANDSHAKE_NO_WAIT`, otherwise set it to `HANDSHAKE_STANDARD`. The default value is `HANDSHAKE_STANDARD`.
|
||||||
9. Please specify a value between 1025 and 65535 for the `rpcPort` property.
|
9. Please specify a value between 1025 and 65535 for the `rpcPort` property.
|
||||||
10. Please specify a value between 1025 and 65535 for the `socks5Port` property. This port cannot be the same as `rpcPort`.
|
10. Please specify a value between 1025 and 65535 for the `socks5Port` property. This port cannot be the same as `rpcPort`.
|
||||||
11. [Optional] If the client needs to provide proxy services to other devices on the LAN, set the `socks5ListenLAN` property to `true`.
|
11. [Optional] If the client needs to provide proxy services to other devices on the LAN, set the `socks5ListenLAN` property to `true`.
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ mieru apply config <FILE>
|
|||||||
"multiplexing": {
|
"multiplexing": {
|
||||||
"level": "MULTIPLEXING_HIGH"
|
"level": "MULTIPLEXING_HIGH"
|
||||||
},
|
},
|
||||||
"handshakeMode": "HANDSHAKE_NO_WAIT"
|
"handshakeMode": "HANDSHAKE_STANDARD"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"activeProfile": "default",
|
"activeProfile": "default",
|
||||||
@@ -69,7 +69,7 @@ mieru apply config <FILE>
|
|||||||
5. 在 `profiles` -> `servers` -> `portBindings` -> `port` 中填写 mita 监听的 TCP 或 UDP 端口号。这个端口号必须与代理服务器中的设置相同。如果想要监听连续的端口号,也可以改为使用 `portRange` 属性。
|
5. 在 `profiles` -> `servers` -> `portBindings` -> `port` 中填写 mita 监听的 TCP 或 UDP 端口号。这个端口号必须与代理服务器中的设置相同。如果想要监听连续的端口号,也可以改为使用 `portRange` 属性。
|
||||||
6. 【可选】请为 `profiles` -> `mtu` 属性中指定一个从 1280 到 1400 之间的值。默认值为 1400。这个值必须与代理服务器相同。
|
6. 【可选】请为 `profiles` -> `mtu` 属性中指定一个从 1280 到 1400 之间的值。默认值为 1400。这个值必须与代理服务器相同。
|
||||||
7. 【可选】如果想要调整多路复用的频率,是更多地创建新连接,还是更多地重用旧连接,可以为 `profiles` -> `multiplexing` -> `level` 属性设定一个值。这里可以使用的值包括 `MULTIPLEXING_OFF`, `MULTIPLEXING_LOW`, `MULTIPLEXING_MIDDLE`, `MULTIPLEXING_HIGH`。其中 `MULTIPLEXING_OFF` 会关闭多路复用功能。默认值为 `MULTIPLEXING_LOW`。
|
7. 【可选】如果想要调整多路复用的频率,是更多地创建新连接,还是更多地重用旧连接,可以为 `profiles` -> `multiplexing` -> `level` 属性设定一个值。这里可以使用的值包括 `MULTIPLEXING_OFF`, `MULTIPLEXING_LOW`, `MULTIPLEXING_MIDDLE`, `MULTIPLEXING_HIGH`。其中 `MULTIPLEXING_OFF` 会关闭多路复用功能。默认值为 `MULTIPLEXING_LOW`。
|
||||||
8. 【可选】如果想开启 0-RTT 握手,请将 `profiles` -> `handshakeMode` 属性的值设置为 `HANDSHAKE_NO_WAIT`,否则请设置为 `HANDSHAKE_STANDARD`。默认值为 `HANDSHAKE_STANDARD`。
|
8. 【可选】如果想开启 0-RTT 握手(实验性功能),请将 `profiles` -> `handshakeMode` 属性的值设置为 `HANDSHAKE_NO_WAIT`,否则请设置为 `HANDSHAKE_STANDARD`。默认值为 `HANDSHAKE_STANDARD`。
|
||||||
9. 请为 `rpcPort` 属性指定一个从 1025 到 65535 之间的数值。
|
9. 请为 `rpcPort` 属性指定一个从 1025 到 65535 之间的数值。
|
||||||
10. 请为 `socks5Port` 属性指定一个从 1025 到 65535 之间的数值。该端口不能与 `rpcPort` 相同。
|
10. 请为 `socks5Port` 属性指定一个从 1025 到 65535 之间的数值。该端口不能与 `rpcPort` 相同。
|
||||||
11. 【可选】如果客户端需要为局域网中的其他设备提供代理服务,请将 `socks5ListenLAN` 属性设置为 `true`。
|
11. 【可选】如果客户端需要为局域网中的其他设备提供代理服务,请将 `socks5ListenLAN` 属性设置为 `true`。
|
||||||
|
|||||||
@@ -462,7 +462,7 @@ class ClientConfig:
|
|||||||
'ipAddress': '',
|
'ipAddress': '',
|
||||||
'portBindings': [{}],
|
'portBindings': [{}],
|
||||||
}],
|
}],
|
||||||
'handshakeMode': 'HANDSHAKE_NO_WAIT'
|
'handshakeMode': 'HANDSHAKE_STANDARD'
|
||||||
}],
|
}],
|
||||||
'activeProfile': 'default',
|
'activeProfile': 'default',
|
||||||
'rpcPort': 0,
|
'rpcPort': 0,
|
||||||
|
|||||||
@@ -5,58 +5,50 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
)
|
)
|
||||||
|
|
||||||
func DefaultValue[T any]() T {
|
|
||||||
var defaultValue T
|
|
||||||
return defaultValue
|
|
||||||
}
|
|
||||||
|
|
||||||
type TypedValue[T any] struct {
|
type TypedValue[T any] struct {
|
||||||
_ noCopy
|
value atomic.Pointer[T]
|
||||||
value atomic.Value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// tValue is a struct with determined type to resolve atomic.Value usages with interface types
|
func (t *TypedValue[T]) Load() (v T) {
|
||||||
// https://github.com/golang/go/issues/22550
|
v, _ = t.LoadOk()
|
||||||
//
|
return
|
||||||
// The intention to have an atomic value store for errors. However, running this code panics:
|
|
||||||
// panic: sync/atomic: store of inconsistently typed value into Value
|
|
||||||
// This is because atomic.Value requires that the underlying concrete type be the same (which is a reasonable expectation for its implementation).
|
|
||||||
// When going through the atomic.Value.Store method call, the fact that both these are of the error interface is lost.
|
|
||||||
type tValue[T any] struct {
|
|
||||||
value T
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TypedValue[T]) Load() T {
|
func (t *TypedValue[T]) LoadOk() (v T, ok bool) {
|
||||||
value, _ := t.LoadOk()
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *TypedValue[T]) LoadOk() (_ T, ok bool) {
|
|
||||||
value := t.value.Load()
|
value := t.value.Load()
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return DefaultValue[T](), false
|
return
|
||||||
}
|
}
|
||||||
return value.(tValue[T]).value, true
|
return *value, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TypedValue[T]) Store(value T) {
|
func (t *TypedValue[T]) Store(value T) {
|
||||||
t.value.Store(tValue[T]{value})
|
t.value.Store(&value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TypedValue[T]) Swap(new T) T {
|
func (t *TypedValue[T]) Swap(new T) (v T) {
|
||||||
old := t.value.Swap(tValue[T]{new})
|
old := t.value.Swap(&new)
|
||||||
if old == nil {
|
if old == nil {
|
||||||
return DefaultValue[T]()
|
return
|
||||||
}
|
}
|
||||||
return old.(tValue[T]).value
|
return *old
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TypedValue[T]) CompareAndSwap(old, new T) bool {
|
func (t *TypedValue[T]) CompareAndSwap(old, new T) bool {
|
||||||
return t.value.CompareAndSwap(tValue[T]{old}, tValue[T]{new}) ||
|
for {
|
||||||
// In the edge-case where [atomic.Value.Store] is uninitialized
|
currentP := t.value.Load()
|
||||||
// and trying to compare with the zero value of T,
|
var currentValue T
|
||||||
// then compare-and-swap with the nil any value.
|
if currentP != nil {
|
||||||
(any(old) == any(DefaultValue[T]()) && t.value.CompareAndSwap(any(nil), tValue[T]{new}))
|
currentValue = *currentP
|
||||||
|
}
|
||||||
|
// Compare old and current via runtime equality check.
|
||||||
|
if any(currentValue) != any(old) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if t.value.CompareAndSwap(currentP, &new) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TypedValue[T]) MarshalJSON() ([]byte, error) {
|
func (t *TypedValue[T]) MarshalJSON() ([]byte, error) {
|
||||||
@@ -89,9 +81,3 @@ func NewTypedValue[T any](t T) (v TypedValue[T]) {
|
|||||||
v.Store(t)
|
v.Store(t)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type noCopy struct{}
|
|
||||||
|
|
||||||
// Lock is a no-op used by -copylocks checker from `go vet`.
|
|
||||||
func (*noCopy) Lock() {}
|
|
||||||
func (*noCopy) Unlock() {}
|
|
||||||
|
|||||||
@@ -7,20 +7,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestTypedValue(t *testing.T) {
|
func TestTypedValue(t *testing.T) {
|
||||||
{
|
|
||||||
// Always wrapping should not allocate for simple values
|
|
||||||
// because tValue[T] has the same memory layout as T.
|
|
||||||
var v TypedValue[bool]
|
|
||||||
bools := []bool{true, false}
|
|
||||||
if n := int(testing.AllocsPerRun(1000, func() {
|
|
||||||
for _, b := range bools {
|
|
||||||
v.Store(b)
|
|
||||||
}
|
|
||||||
})); n != 0 {
|
|
||||||
t.Errorf("AllocsPerRun = %d, want 0", n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
var v TypedValue[int]
|
var v TypedValue[int]
|
||||||
got, gotOk := v.LoadOk()
|
got, gotOk := v.LoadOk()
|
||||||
@@ -58,20 +44,126 @@ func TestTypedValue(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
e1, e2, e3 := io.EOF, &os.PathError{}, &os.PathError{}
|
||||||
|
var v TypedValue[error]
|
||||||
|
if v.CompareAndSwap(e1, e2) != false {
|
||||||
|
t.Fatalf("CompareAndSwap = true, want false")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != nil {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, nil)
|
||||||
|
}
|
||||||
|
if v.CompareAndSwap(nil, e1) != true {
|
||||||
|
t.Fatalf("CompareAndSwap = false, want true")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != e1 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, e1)
|
||||||
|
}
|
||||||
|
if v.CompareAndSwap(e2, e3) != false {
|
||||||
|
t.Fatalf("CompareAndSwap = true, want false")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != e1 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, e1)
|
||||||
|
}
|
||||||
|
if v.CompareAndSwap(e1, e2) != true {
|
||||||
|
t.Fatalf("CompareAndSwap = false, want true")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != e2 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, e2)
|
||||||
|
}
|
||||||
|
if v.CompareAndSwap(e3, e2) != false {
|
||||||
|
t.Fatalf("CompareAndSwap = true, want false")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != e2 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, e2)
|
||||||
|
}
|
||||||
|
if v.CompareAndSwap(nil, e3) != false {
|
||||||
|
t.Fatalf("CompareAndSwap = true, want false")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != e2 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, e2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
c1, c2, c3 := make(chan struct{}), make(chan struct{}), make(chan struct{})
|
c1, c2, c3 := make(chan struct{}), make(chan struct{}), make(chan struct{})
|
||||||
var v TypedValue[chan struct{}]
|
var v TypedValue[chan struct{}]
|
||||||
if v.CompareAndSwap(c1, c2) != false {
|
if v.CompareAndSwap(c1, c2) != false {
|
||||||
t.Fatalf("CompareAndSwap = true, want false")
|
t.Fatalf("CompareAndSwap = true, want false")
|
||||||
}
|
}
|
||||||
|
if value := v.Load(); value != nil {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, nil)
|
||||||
|
}
|
||||||
if v.CompareAndSwap(nil, c1) != true {
|
if v.CompareAndSwap(nil, c1) != true {
|
||||||
t.Fatalf("CompareAndSwap = false, want true")
|
t.Fatalf("CompareAndSwap = false, want true")
|
||||||
}
|
}
|
||||||
|
if value := v.Load(); value != c1 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, c1)
|
||||||
|
}
|
||||||
if v.CompareAndSwap(c2, c3) != false {
|
if v.CompareAndSwap(c2, c3) != false {
|
||||||
t.Fatalf("CompareAndSwap = true, want false")
|
t.Fatalf("CompareAndSwap = true, want false")
|
||||||
}
|
}
|
||||||
|
if value := v.Load(); value != c1 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, c1)
|
||||||
|
}
|
||||||
if v.CompareAndSwap(c1, c2) != true {
|
if v.CompareAndSwap(c1, c2) != true {
|
||||||
t.Fatalf("CompareAndSwap = false, want true")
|
t.Fatalf("CompareAndSwap = false, want true")
|
||||||
}
|
}
|
||||||
|
if value := v.Load(); value != c2 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, c2)
|
||||||
|
}
|
||||||
|
if v.CompareAndSwap(c3, c2) != false {
|
||||||
|
t.Fatalf("CompareAndSwap = true, want false")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != c2 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, c2)
|
||||||
|
}
|
||||||
|
if v.CompareAndSwap(nil, c3) != false {
|
||||||
|
t.Fatalf("CompareAndSwap = true, want false")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != c2 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, c2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
c1, c2, c3 := &io.LimitedReader{}, &io.SectionReader{}, &io.SectionReader{}
|
||||||
|
var v TypedValue[io.Reader]
|
||||||
|
if v.CompareAndSwap(c1, c2) != false {
|
||||||
|
t.Fatalf("CompareAndSwap = true, want false")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != nil {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, nil)
|
||||||
|
}
|
||||||
|
if v.CompareAndSwap(nil, c1) != true {
|
||||||
|
t.Fatalf("CompareAndSwap = false, want true")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != c1 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, c1)
|
||||||
|
}
|
||||||
|
if v.CompareAndSwap(c2, c3) != false {
|
||||||
|
t.Fatalf("CompareAndSwap = true, want false")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != c1 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, c1)
|
||||||
|
}
|
||||||
|
if v.CompareAndSwap(c1, c2) != true {
|
||||||
|
t.Fatalf("CompareAndSwap = false, want true")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != c2 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, c2)
|
||||||
|
}
|
||||||
|
if v.CompareAndSwap(c3, c2) != false {
|
||||||
|
t.Fatalf("CompareAndSwap = true, want false")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != c2 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, c2)
|
||||||
|
}
|
||||||
|
if v.CompareAndSwap(nil, c3) != false {
|
||||||
|
t.Fatalf("CompareAndSwap = true, want false")
|
||||||
|
}
|
||||||
|
if value := v.Load(); value != c2 {
|
||||||
|
t.Fatalf("Load = (%v), want (%v)", value, c2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,27 +10,27 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
keepAliveIdle = atomic.NewTypedValue[time.Duration](0 * time.Second)
|
keepAliveIdle = atomic.NewInt64(0)
|
||||||
keepAliveInterval = atomic.NewTypedValue[time.Duration](0 * time.Second)
|
keepAliveInterval = atomic.NewInt64(0)
|
||||||
disableKeepAlive = atomic.NewBool(false)
|
disableKeepAlive = atomic.NewBool(false)
|
||||||
|
|
||||||
SetDisableKeepAliveCallback = utils.NewCallback[bool]()
|
SetDisableKeepAliveCallback = utils.NewCallback[bool]()
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetKeepAliveIdle(t time.Duration) {
|
func SetKeepAliveIdle(t time.Duration) {
|
||||||
keepAliveIdle.Store(t)
|
keepAliveIdle.Store(int64(t))
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetKeepAliveInterval(t time.Duration) {
|
func SetKeepAliveInterval(t time.Duration) {
|
||||||
keepAliveInterval.Store(t)
|
keepAliveInterval.Store(int64(t))
|
||||||
}
|
}
|
||||||
|
|
||||||
func KeepAliveIdle() time.Duration {
|
func KeepAliveIdle() time.Duration {
|
||||||
return keepAliveIdle.Load()
|
return time.Duration(keepAliveIdle.Load())
|
||||||
}
|
}
|
||||||
|
|
||||||
func KeepAliveInterval() time.Duration {
|
func KeepAliveInterval() time.Duration {
|
||||||
return keepAliveInterval.Load()
|
return time.Duration(keepAliveInterval.Load())
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetDisableKeepAlive(disable bool) {
|
func SetDisableKeepAlive(disable bool) {
|
||||||
|
|||||||
+7
-7
@@ -3,7 +3,6 @@ module github.com/metacubex/mihomo
|
|||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/3andne/restls-client-go v0.1.6
|
|
||||||
github.com/bahlo/generic-list-go v0.2.0
|
github.com/bahlo/generic-list-go v0.2.0
|
||||||
github.com/coreos/go-iptables v0.8.0
|
github.com/coreos/go-iptables v0.8.0
|
||||||
github.com/dlclark/regexp2 v1.11.5
|
github.com/dlclark/regexp2 v1.11.5
|
||||||
@@ -19,18 +18,20 @@ require (
|
|||||||
github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab
|
github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab
|
||||||
github.com/metacubex/bart v0.20.5
|
github.com/metacubex/bart v0.20.5
|
||||||
github.com/metacubex/bbolt v0.0.0-20250725135710-010dbbbb7a5b
|
github.com/metacubex/bbolt v0.0.0-20250725135710-010dbbbb7a5b
|
||||||
|
github.com/metacubex/blake3 v0.1.0
|
||||||
github.com/metacubex/chacha v0.1.5
|
github.com/metacubex/chacha v0.1.5
|
||||||
github.com/metacubex/fswatch v0.1.1
|
github.com/metacubex/fswatch v0.1.1
|
||||||
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759
|
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759
|
||||||
github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295
|
github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295
|
||||||
github.com/metacubex/randv2 v0.2.0
|
github.com/metacubex/randv2 v0.2.0
|
||||||
github.com/metacubex/sing v0.5.4
|
github.com/metacubex/restls-client-go v0.1.7
|
||||||
|
github.com/metacubex/sing v0.5.5
|
||||||
github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac
|
github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac
|
||||||
github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb
|
github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb
|
||||||
github.com/metacubex/sing-shadowsocks v0.2.11
|
github.com/metacubex/sing-shadowsocks v0.2.12
|
||||||
github.com/metacubex/sing-shadowsocks2 v0.2.5
|
github.com/metacubex/sing-shadowsocks2 v0.2.6
|
||||||
github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2
|
github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2
|
||||||
github.com/metacubex/sing-tun v0.4.7-0.20250801130030-308b828865ae
|
github.com/metacubex/sing-tun v0.4.7
|
||||||
github.com/metacubex/sing-vmess v0.2.4-0.20250731011226-ea28d589924d
|
github.com/metacubex/sing-vmess v0.2.4-0.20250731011226-ea28d589924d
|
||||||
github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f
|
github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f
|
||||||
github.com/metacubex/smux v0.0.0-20250503055512-501391591dee
|
github.com/metacubex/smux v0.0.0-20250503055512-501391591dee
|
||||||
@@ -59,7 +60,6 @@ require (
|
|||||||
golang.org/x/sys v0.30.0 // lastest version compatible with golang1.20
|
golang.org/x/sys v0.30.0 // lastest version compatible with golang1.20
|
||||||
google.golang.org/protobuf v1.34.2 // lastest version compatible with golang1.20
|
google.golang.org/protobuf v1.34.2 // lastest version compatible with golang1.20
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
lukechampine.com/blake3 v1.3.0 // lastest version compatible with golang1.20
|
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -85,11 +85,11 @@ require (
|
|||||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||||
github.com/hashicorp/yamux v0.1.2 // indirect
|
github.com/hashicorp/yamux v0.1.2 // indirect
|
||||||
github.com/josharian/native v1.1.0 // indirect
|
github.com/josharian/native v1.1.0 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
|
||||||
github.com/kr/text v0.2.0 // indirect
|
github.com/kr/text v0.2.0 // indirect
|
||||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
github.com/mdlayher/socket v0.4.1 // indirect
|
github.com/mdlayher/socket v0.4.1 // indirect
|
||||||
|
github.com/metacubex/ascon v0.1.0 // indirect
|
||||||
github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b // indirect
|
github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b // indirect
|
||||||
github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 // indirect
|
github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 // indirect
|
||||||
github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect
|
github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect
|
||||||
|
|||||||
+14
-14
@@ -1,5 +1,3 @@
|
|||||||
github.com/3andne/restls-client-go v0.1.6 h1:tRx/YilqW7iHpgmEL4E1D8dAsuB0tFF3uvncS+B6I08=
|
|
||||||
github.com/3andne/restls-client-go v0.1.6/go.mod h1:iEdTZNt9kzPIxjIGSMScUFSBrUH6bFRNg0BWlP4orEY=
|
|
||||||
github.com/RyuaNerin/go-krypto v1.3.0 h1:smavTzSMAx8iuVlGb4pEwl9MD2qicqMzuXR2QWp2/Pg=
|
github.com/RyuaNerin/go-krypto v1.3.0 h1:smavTzSMAx8iuVlGb4pEwl9MD2qicqMzuXR2QWp2/Pg=
|
||||||
github.com/RyuaNerin/go-krypto v1.3.0/go.mod h1:9R9TU936laAIqAmjcHo/LsaXYOZlymudOAxjaBf62UM=
|
github.com/RyuaNerin/go-krypto v1.3.0/go.mod h1:9R9TU936laAIqAmjcHo/LsaXYOZlymudOAxjaBf62UM=
|
||||||
github.com/RyuaNerin/testingutil v0.1.0 h1:IYT6JL57RV3U2ml3dLHZsVtPOP6yNK7WUVdzzlpNrss=
|
github.com/RyuaNerin/testingutil v0.1.0 h1:IYT6JL57RV3U2ml3dLHZsVtPOP6yNK7WUVdzzlpNrss=
|
||||||
@@ -81,8 +79,6 @@ github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtL
|
|||||||
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||||
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||||
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
|
|
||||||
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
|
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
@@ -98,10 +94,14 @@ github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U
|
|||||||
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
|
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
|
||||||
github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab h1:Chbw+/31UC14YFNr78pESt5Vowlc62zziw05JCUqoL4=
|
github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab h1:Chbw+/31UC14YFNr78pESt5Vowlc62zziw05JCUqoL4=
|
||||||
github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab/go.mod h1:xVKK8jC5Sd3hfh7WjmCq+HorehIbrBijaUWmcuKjPcI=
|
github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab/go.mod h1:xVKK8jC5Sd3hfh7WjmCq+HorehIbrBijaUWmcuKjPcI=
|
||||||
|
github.com/metacubex/ascon v0.1.0 h1:6ZWxmXYszT1XXtwkf6nxfFhc/OTtQ9R3Vyj1jN32lGM=
|
||||||
|
github.com/metacubex/ascon v0.1.0/go.mod h1:eV5oim4cVPPdEL8/EYaTZ0iIKARH9pnhAK/fcT5Kacc=
|
||||||
github.com/metacubex/bart v0.20.5 h1:XkgLZ17QxfxkqKdGsojoM2Zu01mmHyyQSFzt2/calTM=
|
github.com/metacubex/bart v0.20.5 h1:XkgLZ17QxfxkqKdGsojoM2Zu01mmHyyQSFzt2/calTM=
|
||||||
github.com/metacubex/bart v0.20.5/go.mod h1:DCcyfP4MC+Zy7sLK7XeGuMw+P5K9mIRsYOBgiE8icsI=
|
github.com/metacubex/bart v0.20.5/go.mod h1:DCcyfP4MC+Zy7sLK7XeGuMw+P5K9mIRsYOBgiE8icsI=
|
||||||
github.com/metacubex/bbolt v0.0.0-20250725135710-010dbbbb7a5b h1:j7dadXD8I2KTmMt8jg1JcaP1ANL3JEObJPdANKcSYPY=
|
github.com/metacubex/bbolt v0.0.0-20250725135710-010dbbbb7a5b h1:j7dadXD8I2KTmMt8jg1JcaP1ANL3JEObJPdANKcSYPY=
|
||||||
github.com/metacubex/bbolt v0.0.0-20250725135710-010dbbbb7a5b/go.mod h1:+WmP0VJZDkDszvpa83HzfUp6QzARl/IKkMorH4+nODw=
|
github.com/metacubex/bbolt v0.0.0-20250725135710-010dbbbb7a5b/go.mod h1:+WmP0VJZDkDszvpa83HzfUp6QzARl/IKkMorH4+nODw=
|
||||||
|
github.com/metacubex/blake3 v0.1.0 h1:KGnjh/56REO7U+cgZA8dnBhxdP7jByrG7hTP+bu6cqY=
|
||||||
|
github.com/metacubex/blake3 v0.1.0/go.mod h1:CCkLdzFrqf7xmxCdhQFvJsRRV2mwOLDoSPg6vUTB9Uk=
|
||||||
github.com/metacubex/chacha v0.1.5 h1:fKWMb/5c7ZrY8Uoqi79PPFxl+qwR7X/q0OrsAubyX2M=
|
github.com/metacubex/chacha v0.1.5 h1:fKWMb/5c7ZrY8Uoqi79PPFxl+qwR7X/q0OrsAubyX2M=
|
||||||
github.com/metacubex/chacha v0.1.5/go.mod h1:Djn9bPZxLTXbJFSeyo0/qzEzQI+gUSSzttuzZM75GH8=
|
github.com/metacubex/chacha v0.1.5/go.mod h1:Djn9bPZxLTXbJFSeyo0/qzEzQI+gUSSzttuzZM75GH8=
|
||||||
github.com/metacubex/fswatch v0.1.1 h1:jqU7C/v+g0qc2RUFgmAOPoVvfl2BXXUXEumn6oQuxhU=
|
github.com/metacubex/fswatch v0.1.1 h1:jqU7C/v+g0qc2RUFgmAOPoVvfl2BXXUXEumn6oQuxhU=
|
||||||
@@ -116,21 +116,23 @@ github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295 h1:8JVlYuE8uS
|
|||||||
github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295/go.mod h1:1lktQFtCD17FZliVypbrDHwbsFSsmz2xz2TRXydvB5c=
|
github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295/go.mod h1:1lktQFtCD17FZliVypbrDHwbsFSsmz2xz2TRXydvB5c=
|
||||||
github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs=
|
github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs=
|
||||||
github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY=
|
github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY=
|
||||||
|
github.com/metacubex/restls-client-go v0.1.7 h1:eCwiXCTQb5WJu9IlgYvDBA1OgrINv58dEe7hcN5H15k=
|
||||||
|
github.com/metacubex/restls-client-go v0.1.7/go.mod h1:BN/U52vPw7j8VTSh2vleD/MnmVKCov84mS5VcjVHH4g=
|
||||||
github.com/metacubex/sing v0.5.2/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w=
|
github.com/metacubex/sing v0.5.2/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w=
|
||||||
github.com/metacubex/sing v0.5.4 h1:a4kAOZmF+OXosbzPEcrSc5QD35/ex+MNuZsrcuWskHk=
|
github.com/metacubex/sing v0.5.5 h1:m5U8iHvRAUxlme3FZlE/LPIGHjU8oMCUzXWGbQQAC1E=
|
||||||
github.com/metacubex/sing v0.5.4/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w=
|
github.com/metacubex/sing v0.5.5/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w=
|
||||||
github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac h1:wDH/Jh/yqWbzPktqJP+Y1cUG8hchcrzKzUxJiSpnaQs=
|
github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac h1:wDH/Jh/yqWbzPktqJP+Y1cUG8hchcrzKzUxJiSpnaQs=
|
||||||
github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac/go.mod h1:3rt1soewn0O6j89GCLmwAQFsq257u0jf2zQSPhTL3Bw=
|
github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac/go.mod h1:3rt1soewn0O6j89GCLmwAQFsq257u0jf2zQSPhTL3Bw=
|
||||||
github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb h1:U/m3h8lp/j7i8zFgfvScLdZa1/Y8dd74oO7iZaQq80s=
|
github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb h1:U/m3h8lp/j7i8zFgfvScLdZa1/Y8dd74oO7iZaQq80s=
|
||||||
github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb/go.mod h1:B60FxaPHjR1SeQB0IiLrgwgvKsaoASfOWdiqhLjmMGA=
|
github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb/go.mod h1:B60FxaPHjR1SeQB0IiLrgwgvKsaoASfOWdiqhLjmMGA=
|
||||||
github.com/metacubex/sing-shadowsocks v0.2.11 h1:p2NGNOdF95e6XvdDKipLj1FRRqR8dnbfC/7pw2CCTlw=
|
github.com/metacubex/sing-shadowsocks v0.2.12 h1:Wqzo8bYXrK5aWqxu/TjlTnYZzAKtKsaFQBdr6IHFaBE=
|
||||||
github.com/metacubex/sing-shadowsocks v0.2.11/go.mod h1:bT1PCTV316zFnlToRMk5zt9HmIQYRBveiT71mplYPfc=
|
github.com/metacubex/sing-shadowsocks v0.2.12/go.mod h1:2e5EIaw0rxKrm1YTRmiMnDulwbGxH9hAFlrwQLQMQkU=
|
||||||
github.com/metacubex/sing-shadowsocks2 v0.2.5 h1:MnPn0hbcDkSJt6TlpI15XImHKK6IqaOwBUGPKyMnJnE=
|
github.com/metacubex/sing-shadowsocks2 v0.2.6 h1:ZR1kYT0f0Vi64iQSS09OdhFfppiNkh7kjgRdMm0SB98=
|
||||||
github.com/metacubex/sing-shadowsocks2 v0.2.5/go.mod h1:Zyh+rAQRyevYfG/COCvDs1c/YMhGqCuknn7QrGmoQIw=
|
github.com/metacubex/sing-shadowsocks2 v0.2.6/go.mod h1:vOEbfKC60txi0ca+yUlqEwOGc3Obl6cnSgx9Gf45KjE=
|
||||||
github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 h1:gXU+MYPm7Wme3/OAY2FFzVq9d9GxPHOqu5AQfg/ddhI=
|
github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 h1:gXU+MYPm7Wme3/OAY2FFzVq9d9GxPHOqu5AQfg/ddhI=
|
||||||
github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2/go.mod h1:mbfboaXauKJNIHJYxQRa+NJs4JU9NZfkA+I33dS2+9E=
|
github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2/go.mod h1:mbfboaXauKJNIHJYxQRa+NJs4JU9NZfkA+I33dS2+9E=
|
||||||
github.com/metacubex/sing-tun v0.4.7-0.20250801130030-308b828865ae h1:hKYGuBaJBLqNmySrYrOGDXXsyxXNaR8omO96QDsRI2s=
|
github.com/metacubex/sing-tun v0.4.7 h1:ZDY/W+1c7PeWWKeKRyUo18fySF/TWjB0i5ui81Ar778=
|
||||||
github.com/metacubex/sing-tun v0.4.7-0.20250801130030-308b828865ae/go.mod h1:2YywXPWW8Z97kTH7RffOeykKzU+l0aiKlglWV1PAS64=
|
github.com/metacubex/sing-tun v0.4.7/go.mod h1:xHecZRwBnKWe6zG9amAK9cXf91lF6blgjBqm+VvOrmU=
|
||||||
github.com/metacubex/sing-vmess v0.2.4-0.20250731011226-ea28d589924d h1:koSVAQiYqU/qtJ527e+wbsEPvTaM39HW75LSvh04IT0=
|
github.com/metacubex/sing-vmess v0.2.4-0.20250731011226-ea28d589924d h1:koSVAQiYqU/qtJ527e+wbsEPvTaM39HW75LSvh04IT0=
|
||||||
github.com/metacubex/sing-vmess v0.2.4-0.20250731011226-ea28d589924d/go.mod h1:21R5R1u90uUvBQF0owoooEu96/SAYYD56nDrwm6nFaM=
|
github.com/metacubex/sing-vmess v0.2.4-0.20250731011226-ea28d589924d/go.mod h1:21R5R1u90uUvBQF0owoooEu96/SAYYD56nDrwm6nFaM=
|
||||||
github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f h1:Sr/DYKYofKHKc4GF3qkRGNuj6XA6c0eqPgEDN+VAsYU=
|
github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f h1:Sr/DYKYofKHKc4GF3qkRGNuj6XA6c0eqPgEDN+VAsYU=
|
||||||
@@ -279,5 +281,3 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33
|
|||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE=
|
|
||||||
lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
tls "github.com/3andne/restls-client-go"
|
tls "github.com/metacubex/restls-client-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import (
|
|||||||
"net/netip"
|
"net/netip"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/metacubex/blake3"
|
||||||
"github.com/metacubex/quic-go"
|
"github.com/metacubex/quic-go"
|
||||||
"lukechampine.com/blake3"
|
|
||||||
|
|
||||||
C "github.com/metacubex/mihomo/constant"
|
C "github.com/metacubex/mihomo/constant"
|
||||||
"github.com/metacubex/mihomo/transport/socks5"
|
"github.com/metacubex/mihomo/transport/socks5"
|
||||||
|
|||||||
@@ -105,26 +105,20 @@ func (vc *Conn) sendRequest(p []byte) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var buffer *buf.Buffer
|
requestLen := 1 // protocol version
|
||||||
if vc.IsXTLSVisionEnabled() {
|
requestLen += 16 // UUID
|
||||||
buffer = buf.New()
|
requestLen += 1 // addons length
|
||||||
defer buffer.Release()
|
requestLen += len(addonsBytes)
|
||||||
} else {
|
requestLen += 1 // command
|
||||||
requestLen := 1 // protocol version
|
if !vc.dst.Mux {
|
||||||
requestLen += 16 // UUID
|
requestLen += 2 // port
|
||||||
requestLen += 1 // addons length
|
requestLen += 1 // addr type
|
||||||
requestLen += len(addonsBytes)
|
requestLen += len(vc.dst.Addr)
|
||||||
requestLen += 1 // command
|
|
||||||
if !vc.dst.Mux {
|
|
||||||
requestLen += 2 // port
|
|
||||||
requestLen += 1 // addr type
|
|
||||||
requestLen += len(vc.dst.Addr)
|
|
||||||
}
|
|
||||||
requestLen += len(p)
|
|
||||||
|
|
||||||
buffer = buf.NewSize(requestLen)
|
|
||||||
defer buffer.Release()
|
|
||||||
}
|
}
|
||||||
|
requestLen += len(p)
|
||||||
|
|
||||||
|
buffer := buf.NewSize(requestLen)
|
||||||
|
defer buffer.Release()
|
||||||
|
|
||||||
buf.Must(
|
buf.Must(
|
||||||
buffer.WriteByte(Version), // protocol version
|
buffer.WriteByte(Version), // protocol version
|
||||||
@@ -182,10 +176,6 @@ func (vc *Conn) NeedHandshake() bool {
|
|||||||
return vc.needHandshake
|
return vc.needHandshake
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vc *Conn) IsXTLSVisionEnabled() bool {
|
|
||||||
return vc.addons != nil && vc.addons.Flow == XRV
|
|
||||||
}
|
|
||||||
|
|
||||||
// newConn return a Conn instance
|
// newConn return a Conn instance
|
||||||
func newConn(conn net.Conn, client *Client, dst *DstAddr) (net.Conn, error) {
|
func newConn(conn net.Conn, client *Client, dst *DstAddr) (net.Conn, error) {
|
||||||
c := &Conn{
|
c := &Conn{
|
||||||
|
|||||||
@@ -4,11 +4,13 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"crypto/sha256"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -36,13 +38,12 @@ func init() {
|
|||||||
|
|
||||||
type ClientInstance struct {
|
type ClientInstance struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
nfsEKey *mlkem.EncapsulationKey768
|
nfsEKey *mlkem.EncapsulationKey768
|
||||||
nfsEKeyBytes []byte
|
xorKey []byte
|
||||||
xor uint32
|
minutes time.Duration
|
||||||
minutes time.Duration
|
expire time.Time
|
||||||
expire time.Time
|
baseKey []byte
|
||||||
baseKey []byte
|
ticket []byte
|
||||||
ticket []byte
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClientConn struct {
|
type ClientConn struct {
|
||||||
@@ -59,10 +60,17 @@ type ClientConn struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *ClientInstance) Init(nfsEKeyBytes []byte, xor uint32, minutes time.Duration) (err error) {
|
func (i *ClientInstance) Init(nfsEKeyBytes []byte, xor uint32, minutes time.Duration) (err error) {
|
||||||
|
if i.nfsEKey != nil {
|
||||||
|
err = errors.New("already initialized")
|
||||||
|
return
|
||||||
|
}
|
||||||
i.nfsEKey, err = mlkem.NewEncapsulationKey768(nfsEKeyBytes)
|
i.nfsEKey, err = mlkem.NewEncapsulationKey768(nfsEKeyBytes)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
if xor > 0 {
|
if xor > 0 {
|
||||||
i.nfsEKeyBytes = nfsEKeyBytes
|
xorKey := sha256.Sum256(nfsEKeyBytes)
|
||||||
i.xor = xor
|
i.xorKey = xorKey[:]
|
||||||
}
|
}
|
||||||
i.minutes = minutes
|
i.minutes = minutes
|
||||||
return
|
return
|
||||||
@@ -72,8 +80,8 @@ func (i *ClientInstance) Handshake(conn net.Conn) (net.Conn, error) {
|
|||||||
if i.nfsEKey == nil {
|
if i.nfsEKey == nil {
|
||||||
return nil, errors.New("uninitialized")
|
return nil, errors.New("uninitialized")
|
||||||
}
|
}
|
||||||
if i.xor > 0 {
|
if i.xorKey != nil {
|
||||||
conn = NewXorConn(conn, i.nfsEKeyBytes)
|
conn = NewXorConn(conn, i.xorKey)
|
||||||
}
|
}
|
||||||
c := &ClientConn{Conn: conn}
|
c := &ClientConn{Conn: conn}
|
||||||
|
|
||||||
@@ -107,16 +115,16 @@ func (i *ClientInstance) Handshake(conn net.Conn) (net.Conn, error) {
|
|||||||
if _, err := c.Conn.Write(clientHello); err != nil {
|
if _, err := c.Conn.Write(clientHello); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// client can send more padding / NFS AEAD messages if needed
|
// client can send more paddings / NFS AEAD messages if needed
|
||||||
|
|
||||||
_, t, l, err := ReadAndDecodeHeader(c.Conn)
|
_, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before server hello
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if t != 1 {
|
if t != 1 {
|
||||||
return nil, fmt.Errorf("unexpected type %v, expect random hello", t)
|
return nil, fmt.Errorf("unexpected type %v, expect random hello", t)
|
||||||
}
|
}
|
||||||
|
|
||||||
peerRandomHello := make([]byte, 1088+21)
|
peerRandomHello := make([]byte, 1088+21)
|
||||||
if l != len(peerRandomHello) {
|
if l != len(peerRandomHello) {
|
||||||
return nil, fmt.Errorf("unexpected length %v for random hello", l)
|
return nil, fmt.Errorf("unexpected length %v for random hello", l)
|
||||||
@@ -193,27 +201,9 @@ func (c *ClientConn) Read(b []byte) (int, error) {
|
|||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
if c.peerAead == nil {
|
if c.peerAead == nil {
|
||||||
var t byte
|
_, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before random hello
|
||||||
var l int
|
if err != nil {
|
||||||
var err error
|
if c.instance != nil && strings.HasPrefix(err.Error(), "invalid header: ") { // 0-RTT's 0-RTT
|
||||||
if c.instance == nil { // from 1-RTT
|
|
||||||
for {
|
|
||||||
if _, t, l, err = ReadAndDecodeHeader(c.Conn); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
if t != 23 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if _, err := io.ReadFull(c.Conn, make([]byte, l)); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
h := make([]byte, 5)
|
|
||||||
if _, err := io.ReadFull(c.Conn, h); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
if t, l, err = DecodeHeader(h); err != nil {
|
|
||||||
c.instance.Lock()
|
c.instance.Lock()
|
||||||
if bytes.Equal(c.ticket, c.instance.ticket) {
|
if bytes.Equal(c.ticket, c.instance.ticket) {
|
||||||
c.instance.expire = time.Now() // expired
|
c.instance.expire = time.Now() // expired
|
||||||
@@ -221,6 +211,7 @@ func (c *ClientConn) Read(b []byte) (int, error) {
|
|||||||
c.instance.Unlock()
|
c.instance.Unlock()
|
||||||
return 0, errors.New("new handshake needed")
|
return 0, errors.New("new handshake needed")
|
||||||
}
|
}
|
||||||
|
return 0, err
|
||||||
}
|
}
|
||||||
if t != 0 {
|
if t != 0 {
|
||||||
return 0, fmt.Errorf("unexpected type %v, expect server random", t)
|
return 0, fmt.Errorf("unexpected type %v, expect server random", t)
|
||||||
|
|||||||
@@ -45,10 +45,10 @@ func DecodeHeader(h []byte) (t byte, l int, err error) {
|
|||||||
} else if h[0] == 1 && h[1] == 1 && h[2] == 1 {
|
} else if h[0] == 1 && h[1] == 1 && h[2] == 1 {
|
||||||
t = 1
|
t = 1
|
||||||
} else {
|
} else {
|
||||||
h = nil
|
l = 0
|
||||||
}
|
}
|
||||||
if h == nil || l < 17 || l > 17000 { // TODO: TLSv1.3 max length
|
if l < 17 || l > 17000 { // TODO: TLSv1.3 max length
|
||||||
err = fmt.Errorf("invalid header: %v", h[:5])
|
err = fmt.Errorf("invalid header: %v", h[:5]) // DO NOT CHANGE: relied by client's Read()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -62,6 +62,17 @@ func ReadAndDecodeHeader(conn net.Conn) (h []byte, t byte, l int, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ReadAndDiscardPaddings(conn net.Conn) (h []byte, t byte, l int, err error) {
|
||||||
|
for {
|
||||||
|
if h, t, l, err = ReadAndDecodeHeader(conn); err != nil || t != 23 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err = io.ReadFull(conn, make([]byte, l)); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func NewAead(c byte, secret, salt, info []byte) (aead cipher.AEAD) {
|
func NewAead(c byte, secret, salt, info []byte) (aead cipher.AEAD) {
|
||||||
key := make([]byte, 32)
|
key := make([]byte, 32)
|
||||||
hkdf.New(sha256.New, secret, salt, info).Read(key)
|
hkdf.New(sha256.New, secret, salt, info).Read(key)
|
||||||
|
|||||||
@@ -9,4 +9,6 @@
|
|||||||
// https://github.com/XTLS/Xray-core/commit/1720be168fa069332c418503d30341fc6e01df7f
|
// https://github.com/XTLS/Xray-core/commit/1720be168fa069332c418503d30341fc6e01df7f
|
||||||
// https://github.com/XTLS/Xray-core/commit/0fd7691d6b28e05922d7a5a9313d97745a51ea63
|
// https://github.com/XTLS/Xray-core/commit/0fd7691d6b28e05922d7a5a9313d97745a51ea63
|
||||||
// https://github.com/XTLS/Xray-core/commit/09cc92c61d9067e0d65c1cae9124664ecfc78f43
|
// https://github.com/XTLS/Xray-core/commit/09cc92c61d9067e0d65c1cae9124664ecfc78f43
|
||||||
|
// https://github.com/XTLS/Xray-core/commit/2807ee432a1fbeb301815647189eacd650b12a8b
|
||||||
|
// https://github.com/XTLS/Xray-core/commit/bfe4820f2f086daf639b1957eb23dc13c843cad1
|
||||||
package encryption
|
package encryption
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"crypto/sha256"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@@ -23,12 +24,11 @@ type ServerSession struct {
|
|||||||
|
|
||||||
type ServerInstance struct {
|
type ServerInstance struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
nfsDKey *mlkem.DecapsulationKey768
|
nfsDKey *mlkem.DecapsulationKey768
|
||||||
nfsEKeyBytes []byte
|
xorKey []byte
|
||||||
xor uint32
|
minutes time.Duration
|
||||||
minutes time.Duration
|
sessions map[[21]byte]*ServerSession
|
||||||
sessions map[[21]byte]*ServerSession
|
closed bool
|
||||||
closed bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServerConn struct {
|
type ServerConn struct {
|
||||||
@@ -45,10 +45,17 @@ type ServerConn struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *ServerInstance) Init(nfsDKeySeed []byte, xor uint32, minutes time.Duration) (err error) {
|
func (i *ServerInstance) Init(nfsDKeySeed []byte, xor uint32, minutes time.Duration) (err error) {
|
||||||
|
if i.nfsDKey != nil {
|
||||||
|
err = errors.New("already initialized")
|
||||||
|
return
|
||||||
|
}
|
||||||
i.nfsDKey, err = mlkem.NewDecapsulationKey768(nfsDKeySeed)
|
i.nfsDKey, err = mlkem.NewDecapsulationKey768(nfsDKeySeed)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
if xor > 0 {
|
if xor > 0 {
|
||||||
i.nfsEKeyBytes = i.nfsDKey.EncapsulationKey().Bytes()
|
xorKey := sha256.Sum256(i.nfsDKey.EncapsulationKey().Bytes())
|
||||||
i.xor = xor
|
i.xorKey = xorKey[:]
|
||||||
}
|
}
|
||||||
if minutes > 0 {
|
if minutes > 0 {
|
||||||
i.minutes = minutes
|
i.minutes = minutes
|
||||||
@@ -85,18 +92,15 @@ func (i *ServerInstance) Handshake(conn net.Conn) (net.Conn, error) {
|
|||||||
if i.nfsDKey == nil {
|
if i.nfsDKey == nil {
|
||||||
return nil, errors.New("uninitialized")
|
return nil, errors.New("uninitialized")
|
||||||
}
|
}
|
||||||
if i.xor > 0 {
|
if i.xorKey != nil {
|
||||||
conn = NewXorConn(conn, i.nfsEKeyBytes)
|
conn = NewXorConn(conn, i.xorKey)
|
||||||
}
|
}
|
||||||
c := &ServerConn{Conn: conn}
|
c := &ServerConn{Conn: conn}
|
||||||
|
|
||||||
_, t, l, err := ReadAndDecodeHeader(c.Conn)
|
_, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before client/ticket hello
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if t == 23 {
|
|
||||||
return nil, errors.New("unexpected data")
|
|
||||||
}
|
|
||||||
|
|
||||||
if t == 0 {
|
if t == 0 {
|
||||||
if i.minutes == 0 {
|
if i.minutes == 0 {
|
||||||
@@ -113,9 +117,13 @@ func (i *ServerInstance) Handshake(conn net.Conn) (net.Conn, error) {
|
|||||||
s := i.sessions[[21]byte(peerTicketHello)]
|
s := i.sessions[[21]byte(peerTicketHello)]
|
||||||
i.RUnlock()
|
i.RUnlock()
|
||||||
if s == nil {
|
if s == nil {
|
||||||
noise := make([]byte, randBetween(100, 1000))
|
noises := make([]byte, randBetween(100, 1000))
|
||||||
rand.Read(noise)
|
var err error
|
||||||
c.Conn.Write(noise) // make client do new handshake
|
for err == nil {
|
||||||
|
rand.Read(noises)
|
||||||
|
_, _, err = DecodeHeader(noises)
|
||||||
|
}
|
||||||
|
c.Conn.Write(noises) // make client do new handshake
|
||||||
return nil, errors.New("expired ticket")
|
return nil, errors.New("expired ticket")
|
||||||
}
|
}
|
||||||
if _, replay := s.randoms.LoadOrStore([32]byte(peerTicketHello[21:]), true); replay {
|
if _, replay := s.randoms.LoadOrStore([32]byte(peerTicketHello[21:]), true); replay {
|
||||||
@@ -165,7 +173,7 @@ func (i *ServerInstance) Handshake(conn net.Conn) (net.Conn, error) {
|
|||||||
if _, err := c.Conn.Write(serverHello); err != nil {
|
if _, err := c.Conn.Write(serverHello); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// server can send more padding / PFS AEAD messages if needed
|
// server can send more paddings / PFS AEAD messages if needed
|
||||||
|
|
||||||
if i.minutes > 0 {
|
if i.minutes > 0 {
|
||||||
i.Lock()
|
i.Lock()
|
||||||
@@ -185,20 +193,10 @@ func (c *ServerConn) Read(b []byte) (int, error) {
|
|||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
if c.peerAead == nil {
|
if c.peerAead == nil {
|
||||||
if c.peerRandom == nil { // from 1-RTT
|
if c.peerRandom == nil { // 1-RTT's 0-RTT
|
||||||
var t byte
|
_, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before ticket hello
|
||||||
var l int
|
if err != nil {
|
||||||
var err error
|
return 0, err
|
||||||
for {
|
|
||||||
if _, t, l, err = ReadAndDecodeHeader(c.Conn); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
if t != 23 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if _, err := io.ReadFull(c.Conn, make([]byte, l)); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if t != 0 {
|
if t != 0 {
|
||||||
return 0, fmt.Errorf("unexpected type %v, expect ticket hello", t)
|
return 0, fmt.Errorf("unexpected type %v, expect ticket hello", t)
|
||||||
|
|||||||
@@ -18,11 +18,11 @@ type XorConn struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewXorConn(conn net.Conn, key []byte) *XorConn {
|
func NewXorConn(conn net.Conn, key []byte) *XorConn {
|
||||||
return &XorConn{Conn: conn, key: key[:16]}
|
return &XorConn{Conn: conn, key: key}
|
||||||
//chacha20.NewUnauthenticatedCipher()
|
//chacha20.NewUnauthenticatedCipher()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *XorConn) Write(b []byte) (int, error) { // two records at most
|
func (c *XorConn) Write(b []byte) (int, error) { // whole one/two records
|
||||||
if len(b) == 0 {
|
if len(b) == 0 {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
@@ -34,10 +34,10 @@ func (c *XorConn) Write(b []byte) (int, error) { // two records at most
|
|||||||
c.ctr = cipher.NewCTR(block, iv)
|
c.ctr = cipher.NewCTR(block, iv)
|
||||||
}
|
}
|
||||||
t, l, _ := DecodeHeader(b)
|
t, l, _ := DecodeHeader(b)
|
||||||
if t != 23 {
|
if t == 23 { // single 23
|
||||||
l += 10 // 5+l+5
|
|
||||||
} else {
|
|
||||||
l = 5
|
l = 5
|
||||||
|
} else { // 1/0 + 23, or noises only
|
||||||
|
l += 10
|
||||||
}
|
}
|
||||||
c.ctr.XORKeyStream(b[:l], b[:l]) // caller MUST discard b
|
c.ctr.XORKeyStream(b[:l], b[:l]) // caller MUST discard b
|
||||||
if iv != nil {
|
if iv != nil {
|
||||||
@@ -73,8 +73,8 @@ func (c *XorConn) Read(b []byte) (int, error) { // 5-bytes, data, 5-bytes...
|
|||||||
return len(b), nil
|
return len(b), nil
|
||||||
}
|
}
|
||||||
c.peerCtr.XORKeyStream(b, b)
|
c.peerCtr.XORKeyStream(b, b)
|
||||||
if c.isHeader {
|
if c.isHeader { // always 5-bytes
|
||||||
if t, _, _ := DecodeHeader(b); t == 23 { // always 5-bytes
|
if t, _, _ := DecodeHeader(b); t == 23 {
|
||||||
c.skipNext = true
|
c.skipNext = true
|
||||||
} else {
|
} else {
|
||||||
c.isHeader = false
|
c.isHeader = false
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package vision
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
gotls "crypto/tls"
|
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -12,7 +11,6 @@ import (
|
|||||||
|
|
||||||
"github.com/metacubex/mihomo/common/buf"
|
"github.com/metacubex/mihomo/common/buf"
|
||||||
N "github.com/metacubex/mihomo/common/net"
|
N "github.com/metacubex/mihomo/common/net"
|
||||||
tlsC "github.com/metacubex/mihomo/component/tls"
|
|
||||||
"github.com/metacubex/mihomo/log"
|
"github.com/metacubex/mihomo/log"
|
||||||
|
|
||||||
"github.com/gofrs/uuid/v5"
|
"github.com/gofrs/uuid/v5"
|
||||||
@@ -181,17 +179,10 @@ func (vc *Conn) WriteBuffer(buffer *buf.Buffer) (err error) {
|
|||||||
buffer.Release()
|
buffer.Release()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
switch underlying := vc.tlsConn.(type) {
|
err = vc.checkTLSVersion()
|
||||||
case *gotls.Conn:
|
if err != nil {
|
||||||
if underlying.ConnectionState().Version != gotls.VersionTLS13 {
|
buffer.Release()
|
||||||
buffer.Release()
|
return err
|
||||||
return ErrNotTLS13
|
|
||||||
}
|
|
||||||
case *tlsC.UConn:
|
|
||||||
if underlying.ConnectionState().Version != tlsC.VersionTLS13 {
|
|
||||||
buffer.Release()
|
|
||||||
return ErrNotTLS13
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
vc.tlsConn = nil
|
vc.tlsConn = nil
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -67,3 +67,21 @@ func NewConn(conn connWithUpstream, userUUID *uuid.UUID) (*Conn, error) {
|
|||||||
c.rawInput = (*bytes.Buffer)(unsafe.Add(p, r.Offset))
|
c.rawInput = (*bytes.Buffer)(unsafe.Add(p, r.Offset))
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (vc *Conn) checkTLSVersion() error {
|
||||||
|
switch underlying := vc.tlsConn.(type) {
|
||||||
|
case *gotls.Conn:
|
||||||
|
if underlying.ConnectionState().Version != gotls.VersionTLS13 {
|
||||||
|
return ErrNotTLS13
|
||||||
|
}
|
||||||
|
case *tlsC.Conn:
|
||||||
|
if underlying.ConnectionState().Version != tlsC.VersionTLS13 {
|
||||||
|
return ErrNotTLS13
|
||||||
|
}
|
||||||
|
case *tlsC.UConn:
|
||||||
|
if underlying.ConnectionState().Version != tlsC.VersionTLS13 {
|
||||||
|
return ErrNotTLS13
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
VERSION="1.23.6"
|
VERSION="1.23.12"
|
||||||
|
|
||||||
mkdir -p $HOME/go
|
mkdir -p $HOME/go
|
||||||
cd $HOME/go
|
cd $HOME/go
|
||||||
|
|||||||
Vendored
+31
-25
@@ -40,13 +40,13 @@ jobs:
|
|||||||
version: ${{ steps.outputs.outputs.version }}
|
version: ${{ steps.outputs.outputs.version }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
|
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24.6
|
go-version: ^1.25.0
|
||||||
- name: Check input version
|
- name: Check input version
|
||||||
if: github.event_name == 'workflow_dispatch'
|
if: github.event_name == 'workflow_dispatch'
|
||||||
run: |-
|
run: |-
|
||||||
@@ -88,13 +88,14 @@ jobs:
|
|||||||
- { os: linux, arch: loong64, debian: loongarch64, rpm: loongarch64, openwrt: "loongarch64_generic" }
|
- { os: linux, arch: loong64, debian: loongarch64, rpm: loongarch64, openwrt: "loongarch64_generic" }
|
||||||
|
|
||||||
- { os: windows, arch: amd64 }
|
- { os: windows, arch: amd64 }
|
||||||
- { os: windows, arch: amd64, legacy_go: true }
|
- { os: windows, arch: amd64, legacy_go123: true, legacy_name: "windows-7" }
|
||||||
- { os: windows, arch: "386" }
|
- { os: windows, arch: "386" }
|
||||||
- { os: windows, arch: "386", legacy_go: true }
|
- { os: windows, arch: "386", legacy_go123: true, legacy_name: "windows-7" }
|
||||||
- { os: windows, arch: arm64 }
|
- { os: windows, arch: arm64 }
|
||||||
|
|
||||||
- { os: darwin, arch: amd64 }
|
- { os: darwin, arch: amd64 }
|
||||||
- { os: darwin, arch: arm64 }
|
- { os: darwin, arch: arm64 }
|
||||||
|
- { os: darwin, arch: amd64, legacy_go124: true, legacy_name: "macos-11" }
|
||||||
|
|
||||||
- { os: android, arch: arm64, ndk: "aarch64-linux-android21" }
|
- { os: android, arch: arm64, ndk: "aarch64-linux-android21" }
|
||||||
- { os: android, arch: arm, ndk: "armv7a-linux-androideabi21" }
|
- { os: android, arch: arm, ndk: "armv7a-linux-androideabi21" }
|
||||||
@@ -102,28 +103,33 @@ jobs:
|
|||||||
- { os: android, arch: "386", ndk: "i686-linux-android21" }
|
- { os: android, arch: "386", ndk: "i686-linux-android21" }
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
|
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
if: ${{ ! matrix.legacy_go }}
|
if: ${{ ! (matrix.legacy_go123 || matrix.legacy_go124) }}
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24.6
|
go-version: ^1.25.0
|
||||||
- name: Cache Legacy Go
|
- name: Setup Go 1.24
|
||||||
if: matrix.require_legacy_go
|
if: matrix.legacy_go124
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: ~1.24.6
|
||||||
|
- name: Cache Go 1.23
|
||||||
|
if: matrix.legacy_go123
|
||||||
id: cache-legacy-go
|
id: cache-legacy-go
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/go/go_legacy
|
~/go/go_legacy
|
||||||
key: go_legacy_1236
|
key: go_legacy_12312
|
||||||
- name: Setup Legacy Go
|
- name: Setup Go 1.23
|
||||||
if: matrix.legacy_go && steps.cache-legacy-go.outputs.cache-hit != 'true'
|
if: matrix.legacy_go123 && steps.cache-legacy-go.outputs.cache-hit != 'true'
|
||||||
run: |-
|
run: |-
|
||||||
.github/setup_legacy_go.sh
|
.github/setup_legacy_go.sh
|
||||||
- name: Setup Legacy Go 2
|
- name: Setup Go 1.23
|
||||||
if: matrix.legacy_go
|
if: matrix.legacy_go123
|
||||||
run: |-
|
run: |-
|
||||||
echo "PATH=$HOME/go/go_legacy/bin:$PATH" >> $GITHUB_ENV
|
echo "PATH=$HOME/go/go_legacy/bin:$PATH" >> $GITHUB_ENV
|
||||||
echo "GOROOT=$HOME/go/go_legacy" >> $GITHUB_ENV
|
echo "GOROOT=$HOME/go/go_legacy" >> $GITHUB_ENV
|
||||||
@@ -184,8 +190,8 @@ jobs:
|
|||||||
DIR_NAME="${DIR_NAME}-${{ matrix.go386 }}"
|
DIR_NAME="${DIR_NAME}-${{ matrix.go386 }}"
|
||||||
elif [[ -n "${{ matrix.gomips }}" && "${{ matrix.gomips }}" != 'hardfloat' ]]; then
|
elif [[ -n "${{ matrix.gomips }}" && "${{ matrix.gomips }}" != 'hardfloat' ]]; then
|
||||||
DIR_NAME="${DIR_NAME}-${{ matrix.gomips }}"
|
DIR_NAME="${DIR_NAME}-${{ matrix.gomips }}"
|
||||||
elif [[ "${{ matrix.legacy_go }}" == 'true' ]]; then
|
elif [[ -n "${{ matrix.legacy_name }}" ]]; then
|
||||||
DIR_NAME="${DIR_NAME}-legacy"
|
DIR_NAME="${DIR_NAME}-legacy-${{ matrix.legacy_name }}"
|
||||||
fi
|
fi
|
||||||
echo "DIR_NAME=${DIR_NAME}" >> "${GITHUB_ENV}"
|
echo "DIR_NAME=${DIR_NAME}" >> "${GITHUB_ENV}"
|
||||||
PKG_VERSION="${{ needs.calculate_version.outputs.version }}"
|
PKG_VERSION="${{ needs.calculate_version.outputs.version }}"
|
||||||
@@ -277,7 +283,7 @@ jobs:
|
|||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: binary-${{ matrix.os }}_${{ matrix.arch }}${{ matrix.goarm && format('v{0}', matrix.goarm) }}${{ matrix.go386 && format('_{0}', matrix.go386) }}${{ matrix.gomips && format('_{0}', matrix.gomips) }}${{ matrix.legacy_go && '-legacy' || '' }}
|
name: binary-${{ matrix.os }}_${{ matrix.arch }}${{ matrix.goarm && format('v{0}', matrix.goarm) }}${{ matrix.go386 && format('_{0}', matrix.go386) }}${{ matrix.gomips && format('_{0}', matrix.gomips) }}${{ matrix.legacy_name && format('-legacy-{0}', matrix.legacy_name) }}
|
||||||
path: "dist"
|
path: "dist"
|
||||||
build_android:
|
build_android:
|
||||||
name: Build Android
|
name: Build Android
|
||||||
@@ -287,14 +293,14 @@ jobs:
|
|||||||
- calculate_version
|
- calculate_version
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
|
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24.6
|
go-version: ^1.25.0
|
||||||
- name: Setup Android NDK
|
- name: Setup Android NDK
|
||||||
id: setup-ndk
|
id: setup-ndk
|
||||||
uses: nttld/setup-ndk@v1
|
uses: nttld/setup-ndk@v1
|
||||||
@@ -367,14 +373,14 @@ jobs:
|
|||||||
- calculate_version
|
- calculate_version
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
|
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24.6
|
go-version: ^1.25.0
|
||||||
- name: Setup Android NDK
|
- name: Setup Android NDK
|
||||||
id: setup-ndk
|
id: setup-ndk
|
||||||
uses: nttld/setup-ndk@v1
|
uses: nttld/setup-ndk@v1
|
||||||
@@ -464,7 +470,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
if: matrix.if
|
if: matrix.if
|
||||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
|
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
@@ -472,7 +478,7 @@ jobs:
|
|||||||
if: matrix.if
|
if: matrix.if
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24.6
|
go-version: ^1.25.0
|
||||||
- name: Setup Xcode stable
|
- name: Setup Xcode stable
|
||||||
if: matrix.if && github.ref == 'refs/heads/main-next'
|
if: matrix.if && github.ref == 'refs/heads/main-next'
|
||||||
run: |-
|
run: |-
|
||||||
@@ -624,7 +630,7 @@ jobs:
|
|||||||
- build_apple
|
- build_apple
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
|
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Cache ghr
|
- name: Cache ghr
|
||||||
@@ -647,7 +653,7 @@ jobs:
|
|||||||
git tag v${{ needs.calculate_version.outputs.version }} -f
|
git tag v${{ needs.calculate_version.outputs.version }} -f
|
||||||
echo "VERSION=${{ needs.calculate_version.outputs.version }}" >> "$GITHUB_ENV"
|
echo "VERSION=${{ needs.calculate_version.outputs.version }}" >> "$GITHUB_ENV"
|
||||||
- name: Download builds
|
- name: Download builds
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v5
|
||||||
with:
|
with:
|
||||||
path: dist
|
path: dist
|
||||||
merge-multiple: true
|
merge-multiple: true
|
||||||
|
|||||||
+2
-2
@@ -39,7 +39,7 @@ jobs:
|
|||||||
echo "ref=$ref"
|
echo "ref=$ref"
|
||||||
echo "ref=$ref" >> $GITHUB_OUTPUT
|
echo "ref=$ref" >> $GITHUB_OUTPUT
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
|
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
|
||||||
with:
|
with:
|
||||||
ref: ${{ steps.ref.outputs.ref }}
|
ref: ${{ steps.ref.outputs.ref }}
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
@@ -107,7 +107,7 @@ jobs:
|
|||||||
echo "latest=$latest"
|
echo "latest=$latest"
|
||||||
echo "latest=$latest" >> $GITHUB_OUTPUT
|
echo "latest=$latest" >> $GITHUB_OUTPUT
|
||||||
- name: Download digests
|
- name: Download digests
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v5
|
||||||
with:
|
with:
|
||||||
path: /tmp/digests
|
path: /tmp/digests
|
||||||
pattern: digests-*
|
pattern: digests-*
|
||||||
|
|||||||
Vendored
+3
-3
@@ -22,15 +22,15 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
|
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24.6
|
go-version: ~1.24.6
|
||||||
- name: golangci-lint
|
- name: golangci-lint
|
||||||
uses: golangci/golangci-lint-action@v6
|
uses: golangci/golangci-lint-action@v8
|
||||||
with:
|
with:
|
||||||
version: latest
|
version: latest
|
||||||
args: --timeout=30m
|
args: --timeout=30m
|
||||||
|
|||||||
Vendored
+6
-6
@@ -24,13 +24,13 @@ jobs:
|
|||||||
version: ${{ steps.outputs.outputs.version }}
|
version: ${{ steps.outputs.outputs.version }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
|
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24.6
|
go-version: ^1.25.0
|
||||||
- name: Check input version
|
- name: Check input version
|
||||||
if: github.event_name == 'workflow_dispatch'
|
if: github.event_name == 'workflow_dispatch'
|
||||||
run: |-
|
run: |-
|
||||||
@@ -65,13 +65,13 @@ jobs:
|
|||||||
- { os: linux, arch: loong64, debian: loongarch64, rpm: loongarch64 }
|
- { os: linux, arch: loong64, debian: loongarch64, rpm: loongarch64 }
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
|
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ^1.24.6
|
go-version: ^1.25.0
|
||||||
- name: Setup Android NDK
|
- name: Setup Android NDK
|
||||||
if: matrix.os == 'android'
|
if: matrix.os == 'android'
|
||||||
uses: nttld/setup-ndk@v1
|
uses: nttld/setup-ndk@v1
|
||||||
@@ -171,7 +171,7 @@ jobs:
|
|||||||
- build
|
- build
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
|
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Set tag
|
- name: Set tag
|
||||||
@@ -180,7 +180,7 @@ jobs:
|
|||||||
git tag v${{ needs.calculate_version.outputs.version }} -f
|
git tag v${{ needs.calculate_version.outputs.version }} -f
|
||||||
echo "VERSION=${{ needs.calculate_version.outputs.version }}" >> "$GITHUB_ENV"
|
echo "VERSION=${{ needs.calculate_version.outputs.version }}" >> "$GITHUB_ENV"
|
||||||
- name: Download builds
|
- name: Download builds
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v5
|
||||||
with:
|
with:
|
||||||
path: dist
|
path: dist
|
||||||
merge-multiple: true
|
merge-multiple: true
|
||||||
|
|||||||
+50
-27
@@ -1,27 +1,6 @@
|
|||||||
linters:
|
version: "2"
|
||||||
disable-all: true
|
|
||||||
enable:
|
|
||||||
- gofumpt
|
|
||||||
- govet
|
|
||||||
- gci
|
|
||||||
- staticcheck
|
|
||||||
- paralleltest
|
|
||||||
- ineffassign
|
|
||||||
|
|
||||||
linters-settings:
|
|
||||||
gci:
|
|
||||||
custom-order: true
|
|
||||||
sections:
|
|
||||||
- standard
|
|
||||||
- prefix(github.com/sagernet/)
|
|
||||||
- default
|
|
||||||
staticcheck:
|
|
||||||
checks:
|
|
||||||
- all
|
|
||||||
- -SA1003
|
|
||||||
|
|
||||||
run:
|
run:
|
||||||
go: "1.23"
|
go: "1.24"
|
||||||
build-tags:
|
build-tags:
|
||||||
- with_gvisor
|
- with_gvisor
|
||||||
- with_quic
|
- with_quic
|
||||||
@@ -30,7 +9,51 @@ run:
|
|||||||
- with_utls
|
- with_utls
|
||||||
- with_acme
|
- with_acme
|
||||||
- with_clash_api
|
- with_clash_api
|
||||||
|
linters:
|
||||||
issues:
|
default: none
|
||||||
exclude-dirs:
|
enable:
|
||||||
- transport/simple-obfs
|
- govet
|
||||||
|
- ineffassign
|
||||||
|
- paralleltest
|
||||||
|
- staticcheck
|
||||||
|
settings:
|
||||||
|
staticcheck:
|
||||||
|
checks:
|
||||||
|
- all
|
||||||
|
- -S1000
|
||||||
|
- -S1008
|
||||||
|
- -S1017
|
||||||
|
- -ST1003
|
||||||
|
- -QF1001
|
||||||
|
- -QF1003
|
||||||
|
- -QF1008
|
||||||
|
exclusions:
|
||||||
|
generated: lax
|
||||||
|
presets:
|
||||||
|
- comments
|
||||||
|
- common-false-positives
|
||||||
|
- legacy
|
||||||
|
- std-error-handling
|
||||||
|
paths:
|
||||||
|
- transport/simple-obfs
|
||||||
|
- third_party$
|
||||||
|
- builtin$
|
||||||
|
- examples$
|
||||||
|
formatters:
|
||||||
|
enable:
|
||||||
|
- gci
|
||||||
|
- gofumpt
|
||||||
|
settings:
|
||||||
|
gci:
|
||||||
|
sections:
|
||||||
|
- standard
|
||||||
|
- prefix(github.com/sagernet/)
|
||||||
|
- default
|
||||||
|
custom-order: true
|
||||||
|
exclusions:
|
||||||
|
generated: lax
|
||||||
|
paths:
|
||||||
|
- transport/simple-obfs
|
||||||
|
- third_party$
|
||||||
|
- builtin$
|
||||||
|
- examples$
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
FROM --platform=$BUILDPLATFORM golang:1.24-alpine AS builder
|
FROM --platform=$BUILDPLATFORM golang:1.25-alpine AS builder
|
||||||
LABEL maintainer="nekohasekai <contact-git@sekai.icu>"
|
LABEL maintainer="nekohasekai <contact-git@sekai.icu>"
|
||||||
COPY . /go/src/github.com/sagernet/sing-box
|
COPY . /go/src/github.com/sagernet/sing-box
|
||||||
WORKDIR /go/src/github.com/sagernet/sing-box
|
WORKDIR /go/src/github.com/sagernet/sing-box
|
||||||
|
|||||||
+3
-3
@@ -45,7 +45,7 @@ lint:
|
|||||||
GOOS=freebsd golangci-lint run ./...
|
GOOS=freebsd golangci-lint run ./...
|
||||||
|
|
||||||
lint_install:
|
lint_install:
|
||||||
go install -v github.com/golangci/golangci-lint/cmd/golangci-lint@latest
|
go install -v github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest
|
||||||
|
|
||||||
proto:
|
proto:
|
||||||
@go run ./cmd/internal/protogen
|
@go run ./cmd/internal/protogen
|
||||||
@@ -245,8 +245,8 @@ lib:
|
|||||||
go run ./cmd/internal/build_libbox -target ios
|
go run ./cmd/internal/build_libbox -target ios
|
||||||
|
|
||||||
lib_install:
|
lib_install:
|
||||||
go install -v github.com/sagernet/gomobile/cmd/gomobile@v0.1.7
|
go install -v github.com/sagernet/gomobile/cmd/gomobile@v0.1.8
|
||||||
go install -v github.com/sagernet/gomobile/cmd/gobind@v0.1.7
|
go install -v github.com/sagernet/gomobile/cmd/gobind@v0.1.8
|
||||||
|
|
||||||
docs:
|
docs:
|
||||||
venv/bin/mkdocs serve
|
venv/bin/mkdocs serve
|
||||||
|
|||||||
@@ -135,8 +135,7 @@ func ExtendContext(ctx context.Context) (context.Context, *InboundContext) {
|
|||||||
|
|
||||||
func OverrideContext(ctx context.Context) context.Context {
|
func OverrideContext(ctx context.Context) context.Context {
|
||||||
if metadata := ContextFrom(ctx); metadata != nil {
|
if metadata := ContextFrom(ctx); metadata != nil {
|
||||||
var newMetadata InboundContext
|
newMetadata := *metadata
|
||||||
newMetadata = *metadata
|
|
||||||
return WithContext(ctx, &newMetadata)
|
return WithContext(ctx, &newMetadata)
|
||||||
}
|
}
|
||||||
return ctx
|
return ctx
|
||||||
|
|||||||
@@ -151,9 +151,7 @@ func testOnce(boxPath string, stackName string, mtu int, multiThread bool, flags
|
|||||||
var sudoArgs []string
|
var sudoArgs []string
|
||||||
if len(flags) > 0 {
|
if len(flags) > 0 {
|
||||||
sudoArgs = append(sudoArgs, "env")
|
sudoArgs = append(sudoArgs, "env")
|
||||||
for _, flag := range flags {
|
sudoArgs = append(sudoArgs, flags...)
|
||||||
sudoArgs = append(sudoArgs, flag)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
sudoArgs = append(sudoArgs, boxPath, "run", "-c", tempConfig.Name())
|
sudoArgs = append(sudoArgs, boxPath, "run", "-c", tempConfig.Name())
|
||||||
boxProcess := shell.Exec("sudo", sudoArgs...)
|
boxProcess := shell.Exec("sudo", sudoArgs...)
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/common/srs"
|
"github.com/sagernet/sing-box/common/srs"
|
||||||
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
|
"github.com/sagernet/sing-box/route/rule"
|
||||||
"github.com/sagernet/sing/common/json"
|
"github.com/sagernet/sing/common/json"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@@ -69,7 +71,7 @@ func compileRuleSet(sourcePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = srs.Write(outputFile, plainRuleSet.Options, plainRuleSet.Version)
|
err = srs.Write(outputFile, plainRuleSet.Options, downgradeRuleSetVersion(plainRuleSet.Version, plainRuleSet.Options))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
outputFile.Close()
|
outputFile.Close()
|
||||||
os.Remove(outputPath)
|
os.Remove(outputPath)
|
||||||
@@ -78,3 +80,18 @@ func compileRuleSet(sourcePath string) error {
|
|||||||
outputFile.Close()
|
outputFile.Close()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func downgradeRuleSetVersion(version uint8, options option.PlainRuleSet) uint8 {
|
||||||
|
if version == C.RuleSetVersion4 && !rule.HasHeadlessRule(options.Rules, func(rule option.DefaultHeadlessRule) bool {
|
||||||
|
return rule.NetworkInterfaceAddress != nil && rule.NetworkInterfaceAddress.Size() > 0 ||
|
||||||
|
len(rule.DefaultInterfaceAddress) > 0
|
||||||
|
}) {
|
||||||
|
version = C.RuleSetVersion3
|
||||||
|
}
|
||||||
|
if version == C.RuleSetVersion3 && !rule.HasHeadlessRule(options.Rules, func(rule option.DefaultHeadlessRule) bool {
|
||||||
|
return len(rule.NetworkType) > 0 || rule.NetworkIsExpensive || rule.NetworkIsConstrained
|
||||||
|
}) {
|
||||||
|
version = C.RuleSetVersion2
|
||||||
|
}
|
||||||
|
return version
|
||||||
|
}
|
||||||
|
|||||||
@@ -271,7 +271,7 @@ func (d *DefaultDialer) DialParallelInterface(ctx context.Context, network strin
|
|||||||
} else {
|
} else {
|
||||||
dialer = d.udpDialer4
|
dialer = d.udpDialer4
|
||||||
}
|
}
|
||||||
fastFallback := time.Now().Sub(d.networkLastFallback.Load()) < C.TCPTimeout
|
fastFallback := time.Since(d.networkLastFallback.Load()) < C.TCPTimeout
|
||||||
var (
|
var (
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
isPrimary bool
|
isPrimary bool
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
|
"github.com/sagernet/sing/common/atomic"
|
||||||
"github.com/sagernet/sing/common/bufio"
|
"github.com/sagernet/sing/common/bufio"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
@@ -22,7 +24,7 @@ type slowOpenConn struct {
|
|||||||
ctx context.Context
|
ctx context.Context
|
||||||
network string
|
network string
|
||||||
destination M.Socksaddr
|
destination M.Socksaddr
|
||||||
conn net.Conn
|
conn atomic.Pointer[net.TCPConn]
|
||||||
create chan struct{}
|
create chan struct{}
|
||||||
done chan struct{}
|
done chan struct{}
|
||||||
access sync.Mutex
|
access sync.Mutex
|
||||||
@@ -50,22 +52,25 @@ func DialSlowContext(dialer *tcpDialer, ctx context.Context, network string, des
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *slowOpenConn) Read(b []byte) (n int, err error) {
|
func (c *slowOpenConn) Read(b []byte) (n int, err error) {
|
||||||
if c.conn == nil {
|
conn := c.conn.Load()
|
||||||
select {
|
if conn != nil {
|
||||||
case <-c.create:
|
return conn.Read(b)
|
||||||
if c.err != nil {
|
}
|
||||||
return 0, c.err
|
select {
|
||||||
}
|
case <-c.create:
|
||||||
case <-c.done:
|
if c.err != nil {
|
||||||
return 0, os.ErrClosed
|
return 0, c.err
|
||||||
}
|
}
|
||||||
|
return c.conn.Load().Read(b)
|
||||||
|
case <-c.done:
|
||||||
|
return 0, os.ErrClosed
|
||||||
}
|
}
|
||||||
return c.conn.Read(b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *slowOpenConn) Write(b []byte) (n int, err error) {
|
func (c *slowOpenConn) Write(b []byte) (n int, err error) {
|
||||||
if c.conn != nil {
|
tcpConn := c.conn.Load()
|
||||||
return c.conn.Write(b)
|
if tcpConn != nil {
|
||||||
|
return tcpConn.Write(b)
|
||||||
}
|
}
|
||||||
c.access.Lock()
|
c.access.Lock()
|
||||||
defer c.access.Unlock()
|
defer c.access.Unlock()
|
||||||
@@ -74,7 +79,7 @@ func (c *slowOpenConn) Write(b []byte) (n int, err error) {
|
|||||||
if c.err != nil {
|
if c.err != nil {
|
||||||
return 0, c.err
|
return 0, c.err
|
||||||
}
|
}
|
||||||
return c.conn.Write(b)
|
return c.conn.Load().Write(b)
|
||||||
case <-c.done:
|
case <-c.done:
|
||||||
return 0, os.ErrClosed
|
return 0, os.ErrClosed
|
||||||
default:
|
default:
|
||||||
@@ -83,7 +88,7 @@ func (c *slowOpenConn) Write(b []byte) (n int, err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
c.err = err
|
c.err = err
|
||||||
} else {
|
} else {
|
||||||
c.conn = conn
|
c.conn.Store(conn.(*net.TCPConn))
|
||||||
}
|
}
|
||||||
n = len(b)
|
n = len(b)
|
||||||
close(c.create)
|
close(c.create)
|
||||||
@@ -93,70 +98,77 @@ func (c *slowOpenConn) Write(b []byte) (n int, err error) {
|
|||||||
func (c *slowOpenConn) Close() error {
|
func (c *slowOpenConn) Close() error {
|
||||||
c.closeOnce.Do(func() {
|
c.closeOnce.Do(func() {
|
||||||
close(c.done)
|
close(c.done)
|
||||||
if c.conn != nil {
|
conn := c.conn.Load()
|
||||||
c.conn.Close()
|
if conn != nil {
|
||||||
|
conn.Close()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *slowOpenConn) LocalAddr() net.Addr {
|
func (c *slowOpenConn) LocalAddr() net.Addr {
|
||||||
if c.conn == nil {
|
conn := c.conn.Load()
|
||||||
|
if conn == nil {
|
||||||
return M.Socksaddr{}
|
return M.Socksaddr{}
|
||||||
}
|
}
|
||||||
return c.conn.LocalAddr()
|
return conn.LocalAddr()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *slowOpenConn) RemoteAddr() net.Addr {
|
func (c *slowOpenConn) RemoteAddr() net.Addr {
|
||||||
if c.conn == nil {
|
conn := c.conn.Load()
|
||||||
|
if conn == nil {
|
||||||
return M.Socksaddr{}
|
return M.Socksaddr{}
|
||||||
}
|
}
|
||||||
return c.conn.RemoteAddr()
|
return conn.RemoteAddr()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *slowOpenConn) SetDeadline(t time.Time) error {
|
func (c *slowOpenConn) SetDeadline(t time.Time) error {
|
||||||
if c.conn == nil {
|
conn := c.conn.Load()
|
||||||
|
if conn == nil {
|
||||||
return os.ErrInvalid
|
return os.ErrInvalid
|
||||||
}
|
}
|
||||||
return c.conn.SetDeadline(t)
|
return conn.SetDeadline(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *slowOpenConn) SetReadDeadline(t time.Time) error {
|
func (c *slowOpenConn) SetReadDeadline(t time.Time) error {
|
||||||
if c.conn == nil {
|
conn := c.conn.Load()
|
||||||
|
if conn == nil {
|
||||||
return os.ErrInvalid
|
return os.ErrInvalid
|
||||||
}
|
}
|
||||||
return c.conn.SetReadDeadline(t)
|
return conn.SetReadDeadline(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *slowOpenConn) SetWriteDeadline(t time.Time) error {
|
func (c *slowOpenConn) SetWriteDeadline(t time.Time) error {
|
||||||
if c.conn == nil {
|
conn := c.conn.Load()
|
||||||
|
if conn == nil {
|
||||||
return os.ErrInvalid
|
return os.ErrInvalid
|
||||||
}
|
}
|
||||||
return c.conn.SetWriteDeadline(t)
|
return conn.SetWriteDeadline(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *slowOpenConn) Upstream() any {
|
func (c *slowOpenConn) Upstream() any {
|
||||||
return c.conn
|
return common.PtrOrNil(c.conn.Load())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *slowOpenConn) ReaderReplaceable() bool {
|
func (c *slowOpenConn) ReaderReplaceable() bool {
|
||||||
return c.conn != nil
|
return c.conn.Load() != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *slowOpenConn) WriterReplaceable() bool {
|
func (c *slowOpenConn) WriterReplaceable() bool {
|
||||||
return c.conn != nil
|
return c.conn.Load() != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *slowOpenConn) LazyHeadroom() bool {
|
func (c *slowOpenConn) LazyHeadroom() bool {
|
||||||
return c.conn == nil
|
return c.conn.Load() == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *slowOpenConn) NeedHandshake() bool {
|
func (c *slowOpenConn) NeedHandshake() bool {
|
||||||
return c.conn == nil
|
return c.conn.Load() == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *slowOpenConn) WriteTo(w io.Writer) (n int64, err error) {
|
func (c *slowOpenConn) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
if c.conn == nil {
|
conn := c.conn.Load()
|
||||||
|
if conn == nil {
|
||||||
select {
|
select {
|
||||||
case <-c.create:
|
case <-c.create:
|
||||||
if c.err != nil {
|
if c.err != nil {
|
||||||
@@ -166,5 +178,5 @@ func (c *slowOpenConn) WriteTo(w io.Writer) (n int64, err error) {
|
|||||||
return 0, c.err
|
return 0, c.err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return bufio.Copy(w, c.conn)
|
return bufio.Copy(w, c.conn.Load())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,5 @@ var uQUICChrome115 = &ja3.ClientHello{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func maybeUQUIC(fingerprint *ja3.ClientHello) bool {
|
func maybeUQUIC(fingerprint *ja3.ClientHello) bool {
|
||||||
if uQUICChrome115.Equals(fingerprint, true) {
|
return !uQUICChrome115.Equals(fingerprint, true)
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import (
|
|||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
"github.com/sagernet/sing/common/domain"
|
"github.com/sagernet/sing/common/domain"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
"github.com/sagernet/sing/common/json/badjson"
|
||||||
|
"github.com/sagernet/sing/common/json/badoption"
|
||||||
"github.com/sagernet/sing/common/varbin"
|
"github.com/sagernet/sing/common/varbin"
|
||||||
|
|
||||||
"go4.org/netipx"
|
"go4.org/netipx"
|
||||||
@@ -41,6 +43,8 @@ const (
|
|||||||
ruleItemNetworkType
|
ruleItemNetworkType
|
||||||
ruleItemNetworkIsExpensive
|
ruleItemNetworkIsExpensive
|
||||||
ruleItemNetworkIsConstrained
|
ruleItemNetworkIsConstrained
|
||||||
|
ruleItemNetworkInterfaceAddress
|
||||||
|
ruleItemDefaultInterfaceAddress
|
||||||
ruleItemFinal uint8 = 0xFF
|
ruleItemFinal uint8 = 0xFF
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -230,6 +234,51 @@ func readDefaultRule(reader varbin.Reader, recover bool) (rule option.DefaultHea
|
|||||||
rule.NetworkIsExpensive = true
|
rule.NetworkIsExpensive = true
|
||||||
case ruleItemNetworkIsConstrained:
|
case ruleItemNetworkIsConstrained:
|
||||||
rule.NetworkIsConstrained = true
|
rule.NetworkIsConstrained = true
|
||||||
|
case ruleItemNetworkInterfaceAddress:
|
||||||
|
rule.NetworkInterfaceAddress = new(badjson.TypedMap[option.InterfaceType, badoption.Listable[badoption.Prefixable]])
|
||||||
|
var size uint64
|
||||||
|
size, err = binary.ReadUvarint(reader)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for i := uint64(0); i < size; i++ {
|
||||||
|
var key uint8
|
||||||
|
err = binary.Read(reader, binary.BigEndian, &key)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var value []badoption.Prefixable
|
||||||
|
var prefixCount uint64
|
||||||
|
prefixCount, err = binary.ReadUvarint(reader)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for j := uint64(0); j < prefixCount; j++ {
|
||||||
|
var prefix netip.Prefix
|
||||||
|
prefix, err = readPrefix(reader)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
value = append(value, badoption.Prefixable(prefix))
|
||||||
|
}
|
||||||
|
rule.NetworkInterfaceAddress.Put(option.InterfaceType(key), value)
|
||||||
|
}
|
||||||
|
case ruleItemDefaultInterfaceAddress:
|
||||||
|
var value []badoption.Prefixable
|
||||||
|
var prefixCount uint64
|
||||||
|
prefixCount, err = binary.ReadUvarint(reader)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for j := uint64(0); j < prefixCount; j++ {
|
||||||
|
var prefix netip.Prefix
|
||||||
|
prefix, err = readPrefix(reader)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
value = append(value, badoption.Prefixable(prefix))
|
||||||
|
}
|
||||||
|
rule.DefaultInterfaceAddress = value
|
||||||
case ruleItemFinal:
|
case ruleItemFinal:
|
||||||
err = binary.Read(reader, binary.BigEndian, &rule.Invert)
|
err = binary.Read(reader, binary.BigEndian, &rule.Invert)
|
||||||
return
|
return
|
||||||
@@ -346,7 +395,7 @@ func writeDefaultRule(writer varbin.Writer, rule option.DefaultHeadlessRule, gen
|
|||||||
}
|
}
|
||||||
if len(rule.NetworkType) > 0 {
|
if len(rule.NetworkType) > 0 {
|
||||||
if generateVersion < C.RuleSetVersion3 {
|
if generateVersion < C.RuleSetVersion3 {
|
||||||
return E.New("network_type rule item is only supported in version 3 or later")
|
return E.New("`network_type` rule item is only supported in version 3 or later")
|
||||||
}
|
}
|
||||||
err = writeRuleItemUint8(writer, ruleItemNetworkType, rule.NetworkType)
|
err = writeRuleItemUint8(writer, ruleItemNetworkType, rule.NetworkType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -354,17 +403,67 @@ func writeDefaultRule(writer varbin.Writer, rule option.DefaultHeadlessRule, gen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if rule.NetworkIsExpensive {
|
if rule.NetworkIsExpensive {
|
||||||
|
if generateVersion < C.RuleSetVersion3 {
|
||||||
|
return E.New("`network_is_expensive` rule item is only supported in version 3 or later")
|
||||||
|
}
|
||||||
err = binary.Write(writer, binary.BigEndian, ruleItemNetworkIsExpensive)
|
err = binary.Write(writer, binary.BigEndian, ruleItemNetworkIsExpensive)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if rule.NetworkIsConstrained {
|
if rule.NetworkIsConstrained {
|
||||||
|
if generateVersion < C.RuleSetVersion3 {
|
||||||
|
return E.New("`network_is_constrained` rule item is only supported in version 3 or later")
|
||||||
|
}
|
||||||
err = binary.Write(writer, binary.BigEndian, ruleItemNetworkIsConstrained)
|
err = binary.Write(writer, binary.BigEndian, ruleItemNetworkIsConstrained)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if rule.NetworkInterfaceAddress != nil && rule.NetworkInterfaceAddress.Size() > 0 {
|
||||||
|
if generateVersion < C.RuleSetVersion4 {
|
||||||
|
return E.New("`network_interface_address` rule item is only supported in version 4 or later")
|
||||||
|
}
|
||||||
|
err = writer.WriteByte(ruleItemNetworkInterfaceAddress)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = varbin.WriteUvarint(writer, uint64(rule.NetworkInterfaceAddress.Size()))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, entry := range rule.NetworkInterfaceAddress.Entries() {
|
||||||
|
err = binary.Write(writer, binary.BigEndian, uint8(entry.Key.Build()))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, rawPrefix := range entry.Value {
|
||||||
|
err = writePrefix(writer, rawPrefix.Build(netip.Prefix{}))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(rule.DefaultInterfaceAddress) > 0 {
|
||||||
|
if generateVersion < C.RuleSetVersion4 {
|
||||||
|
return E.New("`default_interface_address` rule item is only supported in version 4 or later")
|
||||||
|
}
|
||||||
|
err = writer.WriteByte(ruleItemDefaultInterfaceAddress)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = varbin.WriteUvarint(writer, uint64(len(rule.DefaultInterfaceAddress)))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, rawPrefix := range rule.DefaultInterfaceAddress {
|
||||||
|
err = writePrefix(writer, rawPrefix.Build(netip.Prefix{}))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if len(rule.WIFISSID) > 0 {
|
if len(rule.WIFISSID) > 0 {
|
||||||
err = writeRuleItemString(writer, ruleItemWIFISSID, rule.WIFISSID)
|
err = writeRuleItemString(writer, ruleItemWIFISSID, rule.WIFISSID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package srs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"net/netip"
|
||||||
|
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
"github.com/sagernet/sing/common/varbin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func readPrefix(reader varbin.Reader) (netip.Prefix, error) {
|
||||||
|
addrSlice, err := varbin.ReadValue[[]byte](reader, binary.BigEndian)
|
||||||
|
if err != nil {
|
||||||
|
return netip.Prefix{}, err
|
||||||
|
}
|
||||||
|
prefixBits, err := varbin.ReadValue[uint8](reader, binary.BigEndian)
|
||||||
|
if err != nil {
|
||||||
|
return netip.Prefix{}, err
|
||||||
|
}
|
||||||
|
return netip.PrefixFrom(M.AddrFromIP(addrSlice), int(prefixBits)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func writePrefix(writer varbin.Writer, prefix netip.Prefix) error {
|
||||||
|
err := varbin.Write(writer, binary.BigEndian, prefix.Addr().AsSlice())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = binary.Write(writer, binary.BigEndian, uint8(prefix.Bits()))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
|
||||||
"github.com/sagernet/sing-box/common/badtls"
|
"github.com/sagernet/sing-box/common/badtls"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
@@ -16,7 +15,7 @@ import (
|
|||||||
aTLS "github.com/sagernet/sing/common/tls"
|
aTLS "github.com/sagernet/sing/common/tls"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewDialerFromOptions(ctx context.Context, router adapter.Router, dialer N.Dialer, serverAddress string, options option.OutboundTLSOptions) (N.Dialer, error) {
|
func NewDialerFromOptions(ctx context.Context, dialer N.Dialer, serverAddress string, options option.OutboundTLSOptions) (N.Dialer, error) {
|
||||||
if !options.Enabled {
|
if !options.Enabled {
|
||||||
return dialer, nil
|
return dialer, nil
|
||||||
}
|
}
|
||||||
@@ -43,12 +42,6 @@ func ClientHandshake(ctx context.Context, conn net.Conn, config Config) (Conn, e
|
|||||||
ctx, cancel := context.WithTimeout(ctx, C.TCPTimeout)
|
ctx, cancel := context.WithTimeout(ctx, C.TCPTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
tlsConn, err := aTLS.ClientHandshake(ctx, conn, config)
|
tlsConn, err := aTLS.ClientHandshake(ctx, conn, config)
|
||||||
var echErr *tls.ECHRejectionError
|
|
||||||
if errors.As(err, &echErr) && len(echErr.RetryConfigList) > 0 {
|
|
||||||
if echConfig, isECH := config.(ECHCapableConfig); isECH {
|
|
||||||
echConfig.SetECHConfigList(echErr.RetryConfigList)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -61,26 +54,57 @@ func ClientHandshake(ctx context.Context, conn net.Conn, config Config) (Conn, e
|
|||||||
return tlsConn, nil
|
return tlsConn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type Dialer struct {
|
type Dialer interface {
|
||||||
|
N.Dialer
|
||||||
|
DialTLSContext(ctx context.Context, destination M.Socksaddr) (Conn, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type defaultDialer struct {
|
||||||
dialer N.Dialer
|
dialer N.Dialer
|
||||||
config Config
|
config Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDialer(dialer N.Dialer, config Config) N.Dialer {
|
func NewDialer(dialer N.Dialer, config Config) Dialer {
|
||||||
return &Dialer{dialer, config}
|
return &defaultDialer{dialer, config}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Dialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
func (d *defaultDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||||
if network != N.NetworkTCP {
|
if N.NetworkName(network) != N.NetworkTCP {
|
||||||
return nil, os.ErrInvalid
|
return nil, os.ErrInvalid
|
||||||
}
|
}
|
||||||
conn, err := d.dialer.DialContext(ctx, network, destination)
|
return d.DialTLSContext(ctx, destination)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *defaultDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *defaultDialer) DialTLSContext(ctx context.Context, destination M.Socksaddr) (Conn, error) {
|
||||||
|
return d.dialContext(ctx, destination, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *defaultDialer) dialContext(ctx context.Context, destination M.Socksaddr, echRetry bool) (Conn, error) {
|
||||||
|
conn, err := d.dialer.DialContext(ctx, N.NetworkTCP, destination)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return ClientHandshake(ctx, conn, d.config)
|
tlsConn, err := ClientHandshake(ctx, conn, d.config)
|
||||||
|
if err == nil {
|
||||||
|
return tlsConn, nil
|
||||||
|
}
|
||||||
|
conn.Close()
|
||||||
|
if echRetry {
|
||||||
|
var echErr *tls.ECHRejectionError
|
||||||
|
if errors.As(err, &echErr) && len(echErr.RetryConfigList) > 0 {
|
||||||
|
if echConfig, isECH := d.config.(ECHCapableConfig); isECH {
|
||||||
|
echConfig.SetECHConfigList(echErr.RetryConfigList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return d.dialContext(ctx, destination, false)
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Dialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
func (d *defaultDialer) Upstream() any {
|
||||||
return nil, os.ErrInvalid
|
return d.dialer
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ func (s *ECHClientConfig) ClientHandshake(ctx context.Context, conn net.Conn) (a
|
|||||||
func (s *ECHClientConfig) fetchAndHandshake(ctx context.Context, conn net.Conn) (aTLS.Conn, error) {
|
func (s *ECHClientConfig) fetchAndHandshake(ctx context.Context, conn net.Conn) (aTLS.Conn, error) {
|
||||||
s.access.Lock()
|
s.access.Lock()
|
||||||
defer s.access.Unlock()
|
defer s.access.Unlock()
|
||||||
if len(s.ECHConfigList()) == 0 || s.lastTTL == 0 || time.Now().Sub(s.lastUpdate) > s.lastTTL {
|
if len(s.ECHConfigList()) == 0 || s.lastTTL == 0 || time.Since(s.lastUpdate) > s.lastTTL {
|
||||||
message := &mDNS.Msg{
|
message := &mDNS.Msg{
|
||||||
MsgHdr: mDNS.MsgHdr{
|
MsgHdr: mDNS.MsgHdr{
|
||||||
RecursionDesired: true,
|
RecursionDesired: true,
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ const (
|
|||||||
RuleSetVersion1 = 1 + iota
|
RuleSetVersion1 = 1 + iota
|
||||||
RuleSetVersion2
|
RuleSetVersion2
|
||||||
RuleSetVersion3
|
RuleSetVersion3
|
||||||
RuleSetVersionCurrent = RuleSetVersion3
|
RuleSetVersion4
|
||||||
|
RuleSetVersionCurrent = RuleSetVersion4
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ func (c *dnsConfig) serverOffset() uint32 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (conf *dnsConfig) nameList(name string) []string {
|
func (c *dnsConfig) nameList(name string) []string {
|
||||||
l := len(name)
|
l := len(name)
|
||||||
rooted := l > 0 && name[l-1] == '.'
|
rooted := l > 0 && name[l-1] == '.'
|
||||||
if l > 254 || l == 254 && !rooted {
|
if l > 254 || l == 254 && !rooted {
|
||||||
@@ -118,15 +118,15 @@ func (conf *dnsConfig) nameList(name string) []string {
|
|||||||
return []string{name}
|
return []string{name}
|
||||||
}
|
}
|
||||||
|
|
||||||
hasNdots := strings.Count(name, ".") >= conf.ndots
|
hasNdots := strings.Count(name, ".") >= c.ndots
|
||||||
name += "."
|
name += "."
|
||||||
// l++
|
// l++
|
||||||
|
|
||||||
names := make([]string, 0, 1+len(conf.search))
|
names := make([]string, 0, 1+len(c.search))
|
||||||
if hasNdots && !avoidDNS(name) {
|
if hasNdots && !avoidDNS(name) {
|
||||||
names = append(names, name)
|
names = append(names, name)
|
||||||
}
|
}
|
||||||
for _, suffix := range conf.search {
|
for _, suffix := range c.search {
|
||||||
fqdn := name + suffix
|
fqdn := name + suffix
|
||||||
if !avoidDNS(fqdn) && len(fqdn) <= 254 {
|
if !avoidDNS(fqdn) && len(fqdn) <= 254 {
|
||||||
names = append(names, fqdn)
|
names = append(names, fqdn)
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ func RegisterTLS(registry *dns.TransportRegistry) {
|
|||||||
type TLSTransport struct {
|
type TLSTransport struct {
|
||||||
dns.TransportAdapter
|
dns.TransportAdapter
|
||||||
logger logger.ContextLogger
|
logger logger.ContextLogger
|
||||||
dialer N.Dialer
|
dialer tls.Dialer
|
||||||
serverAddr M.Socksaddr
|
serverAddr M.Socksaddr
|
||||||
tlsConfig tls.Config
|
tlsConfig tls.Config
|
||||||
access sync.Mutex
|
access sync.Mutex
|
||||||
@@ -67,7 +67,7 @@ func NewTLSRaw(logger logger.ContextLogger, adapter dns.TransportAdapter, dialer
|
|||||||
return &TLSTransport{
|
return &TLSTransport{
|
||||||
TransportAdapter: adapter,
|
TransportAdapter: adapter,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
dialer: dialer,
|
dialer: tls.NewDialer(dialer, tlsConfig),
|
||||||
serverAddr: serverAddr,
|
serverAddr: serverAddr,
|
||||||
tlsConfig: tlsConfig,
|
tlsConfig: tlsConfig,
|
||||||
}
|
}
|
||||||
@@ -100,15 +100,10 @@ func (t *TLSTransport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.M
|
|||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tcpConn, err := t.dialer.DialContext(ctx, N.NetworkTCP, t.serverAddr)
|
tlsConn, err := t.dialer.DialTLSContext(ctx, t.serverAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
tlsConn, err := tls.ClientHandshake(ctx, tcpConn, t.tlsConfig)
|
|
||||||
if err != nil {
|
|
||||||
tcpConn.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return t.exchange(message, &tlsDNSConn{Conn: tlsConn})
|
return t.exchange(message, &tlsDNSConn{Conn: tlsConn})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,23 @@
|
|||||||
icon: material/alert-decagram
|
icon: material/alert-decagram
|
||||||
---
|
---
|
||||||
|
|
||||||
#### 1.12.1
|
#### 1.13.0-alpha.1
|
||||||
|
|
||||||
|
* Add interface address rule items **1**
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
New interface address rules allow you to dynamically adjust rules based on your network environment.
|
||||||
|
|
||||||
|
See [Route Rule](/configuration/route/rule/), [DNS Route Rule](/configuration/dns/rule/)
|
||||||
|
and [Headless Rule](/configuration/rule-set/headless-rule/).
|
||||||
|
|
||||||
|
### 1.12.1
|
||||||
|
|
||||||
* Fixes and improvements
|
* Fixes and improvements
|
||||||
|
|
||||||
#### 1.12.0
|
### 1.12.0
|
||||||
|
|
||||||
* Refactor DNS servers **1**
|
* Refactor DNS servers **1**
|
||||||
* Add domain resolver options**2**
|
* Add domain resolver options**2**
|
||||||
|
|||||||
@@ -2,6 +2,12 @@
|
|||||||
icon: material/alert-decagram
|
icon: material/alert-decagram
|
||||||
---
|
---
|
||||||
|
|
||||||
|
!!! quote "Changes in sing-box 1.13.0"
|
||||||
|
|
||||||
|
:material-plus: [interface_address](#interface_address)
|
||||||
|
:material-plus: [network_interface_address](#network_interface_address)
|
||||||
|
:material-plus: [default_interface_address](#default_interface_address)
|
||||||
|
|
||||||
!!! quote "Changes in sing-box 1.12.0"
|
!!! quote "Changes in sing-box 1.12.0"
|
||||||
|
|
||||||
:material-plus: [ip_accept_any](#ip_accept_any)
|
:material-plus: [ip_accept_any](#ip_accept_any)
|
||||||
@@ -130,6 +136,19 @@ icon: material/alert-decagram
|
|||||||
],
|
],
|
||||||
"network_is_expensive": false,
|
"network_is_expensive": false,
|
||||||
"network_is_constrained": false,
|
"network_is_constrained": false,
|
||||||
|
"interface_address": {
|
||||||
|
"en0": [
|
||||||
|
"2000::/3"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"network_interface_address": {
|
||||||
|
"wifi": [
|
||||||
|
"2000::/3"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"default_interface_address": [
|
||||||
|
"2000::/3"
|
||||||
|
],
|
||||||
"wifi_ssid": [
|
"wifi_ssid": [
|
||||||
"My WIFI"
|
"My WIFI"
|
||||||
],
|
],
|
||||||
@@ -359,6 +378,36 @@ such as Cellular or a Personal Hotspot (on Apple platforms).
|
|||||||
|
|
||||||
Match if network is in Low Data Mode.
|
Match if network is in Low Data Mode.
|
||||||
|
|
||||||
|
#### interface_address
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.13.0"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
Only supported on Linux, Windows, and macOS.
|
||||||
|
|
||||||
|
Match interface address.
|
||||||
|
|
||||||
|
#### network_interface_address
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.13.0"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
Only supported in graphical clients on Android and Apple platforms.
|
||||||
|
|
||||||
|
Matches network interface (same values as `network_type`) address.
|
||||||
|
|
||||||
|
#### default_interface_address
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.13.0"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
Only supported on Linux, Windows, and macOS.
|
||||||
|
|
||||||
|
Match default interface address.
|
||||||
|
|
||||||
#### wifi_ssid
|
#### wifi_ssid
|
||||||
|
|
||||||
!!! quote ""
|
!!! quote ""
|
||||||
|
|||||||
@@ -2,6 +2,12 @@
|
|||||||
icon: material/alert-decagram
|
icon: material/alert-decagram
|
||||||
---
|
---
|
||||||
|
|
||||||
|
!!! quote "sing-box 1.13.0 中的更改"
|
||||||
|
|
||||||
|
:material-plus: [interface_address](#interface_address)
|
||||||
|
:material-plus: [network_interface_address](#network_interface_address)
|
||||||
|
:material-plus: [default_interface_address](#default_interface_address)
|
||||||
|
|
||||||
!!! quote "sing-box 1.12.0 中的更改"
|
!!! quote "sing-box 1.12.0 中的更改"
|
||||||
|
|
||||||
:material-plus: [ip_accept_any](#ip_accept_any)
|
:material-plus: [ip_accept_any](#ip_accept_any)
|
||||||
@@ -130,6 +136,19 @@ icon: material/alert-decagram
|
|||||||
],
|
],
|
||||||
"network_is_expensive": false,
|
"network_is_expensive": false,
|
||||||
"network_is_constrained": false,
|
"network_is_constrained": false,
|
||||||
|
"interface_address": {
|
||||||
|
"en0": [
|
||||||
|
"2000::/3"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"network_interface_address": {
|
||||||
|
"wifi": [
|
||||||
|
"2000::/3"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"default_interface_address": [
|
||||||
|
"2000::/3"
|
||||||
|
],
|
||||||
"wifi_ssid": [
|
"wifi_ssid": [
|
||||||
"My WIFI"
|
"My WIFI"
|
||||||
],
|
],
|
||||||
@@ -358,6 +377,36 @@ Available values: `wifi`, `cellular`, `ethernet` and `other`.
|
|||||||
|
|
||||||
匹配如果网络在低数据模式下。
|
匹配如果网络在低数据模式下。
|
||||||
|
|
||||||
|
#### interface_address
|
||||||
|
|
||||||
|
!!! question "自 sing-box 1.13.0 起"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
仅支持 Linux、Windows 和 macOS.
|
||||||
|
|
||||||
|
匹配接口地址。
|
||||||
|
|
||||||
|
#### network_interface_address
|
||||||
|
|
||||||
|
!!! question "自 sing-box 1.13.0 起"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
仅在 Android 与 Apple 平台图形客户端中支持。
|
||||||
|
|
||||||
|
匹配网络接口(可用值同 `network_type`)地址。
|
||||||
|
|
||||||
|
#### default_interface_address
|
||||||
|
|
||||||
|
!!! question "自 sing-box 1.13.0 起"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
仅支持 Linux、Windows 和 macOS.
|
||||||
|
|
||||||
|
匹配默认接口地址。
|
||||||
|
|
||||||
#### wifi_ssid
|
#### wifi_ssid
|
||||||
|
|
||||||
!!! quote ""
|
!!! quote ""
|
||||||
|
|||||||
@@ -2,6 +2,12 @@
|
|||||||
icon: material/new-box
|
icon: material/new-box
|
||||||
---
|
---
|
||||||
|
|
||||||
|
!!! quote "Changes in sing-box 1.13.0"
|
||||||
|
|
||||||
|
:material-plus: [interface_address](#interface_address)
|
||||||
|
:material-plus: [network_interface_address](#network_interface_address)
|
||||||
|
:material-plus: [default_interface_address](#default_interface_address)
|
||||||
|
|
||||||
!!! quote "Changes in sing-box 1.11.0"
|
!!! quote "Changes in sing-box 1.11.0"
|
||||||
|
|
||||||
:material-plus: [action](#action)
|
:material-plus: [action](#action)
|
||||||
@@ -128,6 +134,19 @@ icon: material/new-box
|
|||||||
],
|
],
|
||||||
"network_is_expensive": false,
|
"network_is_expensive": false,
|
||||||
"network_is_constrained": false,
|
"network_is_constrained": false,
|
||||||
|
"interface_address": {
|
||||||
|
"en0": [
|
||||||
|
"2000::/3"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"network_interface_address": {
|
||||||
|
"wifi": [
|
||||||
|
"2000::/3"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"default_interface_address": [
|
||||||
|
"2000::/3"
|
||||||
|
],
|
||||||
"wifi_ssid": [
|
"wifi_ssid": [
|
||||||
"My WIFI"
|
"My WIFI"
|
||||||
],
|
],
|
||||||
@@ -363,6 +382,36 @@ such as Cellular or a Personal Hotspot (on Apple platforms).
|
|||||||
|
|
||||||
Match if network is in Low Data Mode.
|
Match if network is in Low Data Mode.
|
||||||
|
|
||||||
|
#### interface_address
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.13.0"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
Only supported on Linux, Windows, and macOS.
|
||||||
|
|
||||||
|
Match interface address.
|
||||||
|
|
||||||
|
#### network_interface_address
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.13.0"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
Only supported in graphical clients on Android and Apple platforms.
|
||||||
|
|
||||||
|
Matches network interface (same values as `network_type`) address.
|
||||||
|
|
||||||
|
#### default_interface_address
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.13.0"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
Only supported on Linux, Windows, and macOS.
|
||||||
|
|
||||||
|
Match default interface address.
|
||||||
|
|
||||||
#### wifi_ssid
|
#### wifi_ssid
|
||||||
|
|
||||||
!!! quote ""
|
!!! quote ""
|
||||||
|
|||||||
@@ -2,6 +2,12 @@
|
|||||||
icon: material/new-box
|
icon: material/new-box
|
||||||
---
|
---
|
||||||
|
|
||||||
|
!!! quote "sing-box 1.13.0 中的更改"
|
||||||
|
|
||||||
|
:material-plus: [interface_address](#interface_address)
|
||||||
|
:material-plus: [network_interface_address](#network_interface_address)
|
||||||
|
:material-plus: [default_interface_address](#default_interface_address)
|
||||||
|
|
||||||
!!! quote "sing-box 1.11.0 中的更改"
|
!!! quote "sing-box 1.11.0 中的更改"
|
||||||
|
|
||||||
:material-plus: [action](#action)
|
:material-plus: [action](#action)
|
||||||
@@ -125,6 +131,19 @@ icon: material/new-box
|
|||||||
],
|
],
|
||||||
"network_is_expensive": false,
|
"network_is_expensive": false,
|
||||||
"network_is_constrained": false,
|
"network_is_constrained": false,
|
||||||
|
"interface_address": {
|
||||||
|
"en0": [
|
||||||
|
"2000::/3"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"network_interface_address": {
|
||||||
|
"wifi": [
|
||||||
|
"2000::/3"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"default_interface_address": [
|
||||||
|
"2000::/3"
|
||||||
|
],
|
||||||
"wifi_ssid": [
|
"wifi_ssid": [
|
||||||
"My WIFI"
|
"My WIFI"
|
||||||
],
|
],
|
||||||
@@ -337,7 +356,7 @@ icon: material/new-box
|
|||||||
|
|
||||||
匹配网络类型。
|
匹配网络类型。
|
||||||
|
|
||||||
Available values: `wifi`, `cellular`, `ethernet` and `other`.
|
可用值: `wifi`, `cellular`, `ethernet` and `other`.
|
||||||
|
|
||||||
#### network_is_expensive
|
#### network_is_expensive
|
||||||
|
|
||||||
@@ -360,6 +379,36 @@ Available values: `wifi`, `cellular`, `ethernet` and `other`.
|
|||||||
|
|
||||||
匹配如果网络在低数据模式下。
|
匹配如果网络在低数据模式下。
|
||||||
|
|
||||||
|
#### interface_address
|
||||||
|
|
||||||
|
!!! question "自 sing-box 1.13.0 起"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
仅支持 Linux、Windows 和 macOS.
|
||||||
|
|
||||||
|
匹配接口地址。
|
||||||
|
|
||||||
|
#### network_interface_address
|
||||||
|
|
||||||
|
!!! question "自 sing-box 1.13.0 起"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
仅在 Android 与 Apple 平台图形客户端中支持。
|
||||||
|
|
||||||
|
匹配网络接口(可用值同 `network_type`)地址。
|
||||||
|
|
||||||
|
#### default_interface_address
|
||||||
|
|
||||||
|
!!! question "自 sing-box 1.13.0 起"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
仅支持 Linux、Windows 和 macOS.
|
||||||
|
|
||||||
|
匹配默认接口地址。
|
||||||
|
|
||||||
#### wifi_ssid
|
#### wifi_ssid
|
||||||
|
|
||||||
!!! quote ""
|
!!! quote ""
|
||||||
|
|||||||
@@ -2,6 +2,11 @@
|
|||||||
icon: material/new-box
|
icon: material/new-box
|
||||||
---
|
---
|
||||||
|
|
||||||
|
!!! quote "Changes in sing-box 1.13.0"
|
||||||
|
|
||||||
|
:material-plus: [network_interface_address](#network_interface_address)
|
||||||
|
:material-plus: [default_interface_address](#default_interface_address)
|
||||||
|
|
||||||
!!! quote "Changes in sing-box 1.11.0"
|
!!! quote "Changes in sing-box 1.11.0"
|
||||||
|
|
||||||
:material-plus: [network_type](#network_type)
|
:material-plus: [network_type](#network_type)
|
||||||
@@ -78,6 +83,14 @@ icon: material/new-box
|
|||||||
],
|
],
|
||||||
"network_is_expensive": false,
|
"network_is_expensive": false,
|
||||||
"network_is_constrained": false,
|
"network_is_constrained": false,
|
||||||
|
"network_interface_address": {
|
||||||
|
"wifi": [
|
||||||
|
"2000::/3"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"default_interface_address": [
|
||||||
|
"2000::/3"
|
||||||
|
],
|
||||||
"wifi_ssid": [
|
"wifi_ssid": [
|
||||||
"My WIFI"
|
"My WIFI"
|
||||||
],
|
],
|
||||||
@@ -225,6 +238,26 @@ such as Cellular or a Personal Hotspot (on Apple platforms).
|
|||||||
|
|
||||||
Match if network is in Low Data Mode.
|
Match if network is in Low Data Mode.
|
||||||
|
|
||||||
|
#### network_interface_address
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.13.0"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
Only supported in graphical clients on Android and Apple platforms.
|
||||||
|
|
||||||
|
Matches network interface (same values as `network_type`) address.
|
||||||
|
|
||||||
|
#### default_interface_address
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.13.0"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
Only supported on Linux, Windows, and macOS.
|
||||||
|
|
||||||
|
Match default interface address.
|
||||||
|
|
||||||
#### wifi_ssid
|
#### wifi_ssid
|
||||||
|
|
||||||
!!! quote ""
|
!!! quote ""
|
||||||
|
|||||||
@@ -2,6 +2,11 @@
|
|||||||
icon: material/new-box
|
icon: material/new-box
|
||||||
---
|
---
|
||||||
|
|
||||||
|
!!! quote "sing-box 1.13.0 中的更改"
|
||||||
|
|
||||||
|
:material-plus: [network_interface_address](#network_interface_address)
|
||||||
|
:material-plus: [default_interface_address](#default_interface_address)
|
||||||
|
|
||||||
!!! quote "sing-box 1.11.0 中的更改"
|
!!! quote "sing-box 1.11.0 中的更改"
|
||||||
|
|
||||||
:material-plus: [network_type](#network_type)
|
:material-plus: [network_type](#network_type)
|
||||||
@@ -78,6 +83,14 @@ icon: material/new-box
|
|||||||
],
|
],
|
||||||
"network_is_expensive": false,
|
"network_is_expensive": false,
|
||||||
"network_is_constrained": false,
|
"network_is_constrained": false,
|
||||||
|
"network_interface_address": {
|
||||||
|
"wifi": [
|
||||||
|
"2000::/3"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"default_interface_address": [
|
||||||
|
"2000::/3"
|
||||||
|
],
|
||||||
"wifi_ssid": [
|
"wifi_ssid": [
|
||||||
"My WIFI"
|
"My WIFI"
|
||||||
],
|
],
|
||||||
@@ -221,6 +234,26 @@ Available values: `wifi`, `cellular`, `ethernet` and `other`.
|
|||||||
|
|
||||||
匹配如果网络在低数据模式下。
|
匹配如果网络在低数据模式下。
|
||||||
|
|
||||||
|
#### network_interface_address
|
||||||
|
|
||||||
|
!!! question "自 sing-box 1.13.0 起"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
仅在 Android 与 Apple 平台图形客户端中支持。
|
||||||
|
|
||||||
|
匹配网络接口(可用值同 `network_type`)地址。
|
||||||
|
|
||||||
|
#### default_interface_address
|
||||||
|
|
||||||
|
!!! question "自 sing-box 1.13.0 起"
|
||||||
|
|
||||||
|
!!! quote ""
|
||||||
|
|
||||||
|
仅支持 Linux、Windows 和 macOS.
|
||||||
|
|
||||||
|
匹配默认接口地址。
|
||||||
|
|
||||||
#### wifi_ssid
|
#### wifi_ssid
|
||||||
|
|
||||||
!!! quote ""
|
!!! quote ""
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
icon: material/new-box
|
icon: material/new-box
|
||||||
---
|
---
|
||||||
|
|
||||||
|
!!! quote "Changes in sing-box 1.13.0"
|
||||||
|
|
||||||
|
:material-plus: version `4`
|
||||||
|
|
||||||
!!! quote "Changes in sing-box 1.11.0"
|
!!! quote "Changes in sing-box 1.11.0"
|
||||||
|
|
||||||
:material-plus: version `3`
|
:material-plus: version `3`
|
||||||
@@ -36,6 +40,7 @@ Version of rule-set.
|
|||||||
* 1: sing-box 1.8.0: Initial rule-set version.
|
* 1: sing-box 1.8.0: Initial rule-set version.
|
||||||
* 2: sing-box 1.10.0: Optimized memory usages of `domain_suffix` rules in binary rule-sets.
|
* 2: sing-box 1.10.0: Optimized memory usages of `domain_suffix` rules in binary rule-sets.
|
||||||
* 3: sing-box 1.11.0: Added `network_type`, `network_is_expensive` and `network_is_constrainted` rule items.
|
* 3: sing-box 1.11.0: Added `network_type`, `network_is_expensive` and `network_is_constrainted` rule items.
|
||||||
|
* 4: sing-box 1.13.0: Added `network_interface_address` and `default_interface_address` rule items.
|
||||||
|
|
||||||
#### rules
|
#### rules
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
icon: material/new-box
|
icon: material/new-box
|
||||||
---
|
---
|
||||||
|
|
||||||
|
!!! quote "sing-box 1.13.0 中的更改"
|
||||||
|
|
||||||
|
:material-plus: version `4`
|
||||||
|
|
||||||
!!! quote "sing-box 1.11.0 中的更改"
|
!!! quote "sing-box 1.11.0 中的更改"
|
||||||
|
|
||||||
:material-plus: version `3`
|
:material-plus: version `3`
|
||||||
@@ -36,6 +40,7 @@ icon: material/new-box
|
|||||||
* 1: sing-box 1.8.0: 初始规则集版本。
|
* 1: sing-box 1.8.0: 初始规则集版本。
|
||||||
* 2: sing-box 1.10.0: 优化了二进制规则集中 `domain_suffix` 规则的内存使用。
|
* 2: sing-box 1.10.0: 优化了二进制规则集中 `domain_suffix` 规则的内存使用。
|
||||||
* 3: sing-box 1.11.0: 添加了 `network_type`、 `network_is_expensive` 和 `network_is_constrainted` 规则项。
|
* 3: sing-box 1.11.0: 添加了 `network_type`、 `network_is_expensive` 和 `network_is_constrainted` 规则项。
|
||||||
|
* 4: sing-box 1.13.0: 添加了 `network_interface_address` 和 `default_interface_address` 规则项。
|
||||||
|
|
||||||
#### rules
|
#### rules
|
||||||
|
|
||||||
|
|||||||
@@ -62,10 +62,7 @@ func (s *CommandServer) handleURLTest(conn net.Conn) error {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_, isGroup := it.(adapter.OutboundGroup)
|
_, isGroup := it.(adapter.OutboundGroup)
|
||||||
if isGroup {
|
return !isGroup
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
})
|
})
|
||||||
b, _ := batch.New(serviceNow.ctx, batch.WithConcurrencyNum[any](10))
|
b, _ := batch.New(serviceNow.ctx, batch.WithConcurrencyNum[any](10))
|
||||||
for _, detour := range outbounds {
|
for _, detour := range outbounds {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ func newIterator[T any](values []T) *iterator[T] {
|
|||||||
return &iterator[T]{values}
|
return &iterator[T]{values}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
func newPtrIterator[T any](values []T) *iterator[*T] {
|
func newPtrIterator[T any](values []T) *iterator[*T] {
|
||||||
return &iterator[*T]{common.Map(values, func(value T) *T { return &value })}
|
return &iterator[*T]{common.Map(values, func(value T) *T { return &value })}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ func (s *StatsService) RoutedPacketConnection(ctx context.Context, conn N.Packet
|
|||||||
writeCounter = append(writeCounter, s.loadOrCreateCounter("user>>>"+user+">>>traffic>>>downlink"))
|
writeCounter = append(writeCounter, s.loadOrCreateCounter("user>>>"+user+">>>traffic>>>downlink"))
|
||||||
}
|
}
|
||||||
s.access.Unlock()
|
s.access.Unlock()
|
||||||
return bufio.NewInt64CounterPacketConn(conn, readCounter, writeCounter)
|
return bufio.NewInt64CounterPacketConn(conn, readCounter, nil, writeCounter, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StatsService) GetStats(ctx context.Context, request *GetStatsRequest) (*GetStatsResponse, error) {
|
func (s *StatsService) GetStats(ctx context.Context, request *GetStatsRequest) (*GetStatsResponse, error) {
|
||||||
@@ -192,7 +192,7 @@ func (s *StatsService) GetSysStats(ctx context.Context, request *SysStatsRequest
|
|||||||
var rtm runtime.MemStats
|
var rtm runtime.MemStats
|
||||||
runtime.ReadMemStats(&rtm)
|
runtime.ReadMemStats(&rtm)
|
||||||
response := &SysStatsResponse{
|
response := &SysStatsResponse{
|
||||||
Uptime: uint32(time.Now().Sub(s.createdAt).Seconds()),
|
Uptime: uint32(time.Since(s.createdAt).Seconds()),
|
||||||
NumGoroutine: uint32(runtime.NumGoroutine()),
|
NumGoroutine: uint32(runtime.NumGoroutine()),
|
||||||
Alloc: rtm.Alloc,
|
Alloc: rtm.Alloc,
|
||||||
TotalAlloc: rtm.TotalAlloc,
|
TotalAlloc: rtm.TotalAlloc,
|
||||||
|
|||||||
+11
-11
@@ -24,12 +24,12 @@ require (
|
|||||||
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
|
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
|
||||||
github.com/sagernet/cors v1.2.1
|
github.com/sagernet/cors v1.2.1
|
||||||
github.com/sagernet/fswatch v0.1.1
|
github.com/sagernet/fswatch v0.1.1
|
||||||
github.com/sagernet/gomobile v0.1.7
|
github.com/sagernet/gomobile v0.1.8
|
||||||
github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb
|
github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb
|
||||||
github.com/sagernet/quic-go v0.52.0-beta.1
|
github.com/sagernet/quic-go v0.52.0-beta.1
|
||||||
github.com/sagernet/sing v0.7.5
|
github.com/sagernet/sing v0.7.6-0.20250814022454-614cd851ca6d
|
||||||
github.com/sagernet/sing-mux v0.3.2
|
github.com/sagernet/sing-mux v0.3.3
|
||||||
github.com/sagernet/sing-quic v0.5.0-beta.3
|
github.com/sagernet/sing-quic v0.5.0
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.8
|
github.com/sagernet/sing-shadowsocks v0.2.8
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.2.1
|
github.com/sagernet/sing-shadowsocks2 v0.2.1
|
||||||
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11
|
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11
|
||||||
@@ -44,11 +44,11 @@ require (
|
|||||||
github.com/vishvananda/netns v0.0.5
|
github.com/vishvananda/netns v0.0.5
|
||||||
go.uber.org/zap v1.27.0
|
go.uber.org/zap v1.27.0
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
||||||
golang.org/x/crypto v0.40.0
|
golang.org/x/crypto v0.41.0
|
||||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6
|
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6
|
||||||
golang.org/x/mod v0.26.0
|
golang.org/x/mod v0.27.0
|
||||||
golang.org/x/net v0.42.0
|
golang.org/x/net v0.43.0
|
||||||
golang.org/x/sys v0.34.0
|
golang.org/x/sys v0.35.0
|
||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10
|
||||||
google.golang.org/grpc v1.73.0
|
google.golang.org/grpc v1.73.0
|
||||||
google.golang.org/protobuf v1.36.6
|
google.golang.org/protobuf v1.36.6
|
||||||
@@ -123,10 +123,10 @@ require (
|
|||||||
go.uber.org/zap/exp v0.3.0 // indirect
|
go.uber.org/zap/exp v0.3.0 // indirect
|
||||||
go4.org/mem v0.0.0-20240501181205-ae6ca9944745 // indirect
|
go4.org/mem v0.0.0-20240501181205-ae6ca9944745 // indirect
|
||||||
golang.org/x/sync v0.16.0 // indirect
|
golang.org/x/sync v0.16.0 // indirect
|
||||||
golang.org/x/term v0.33.0 // indirect
|
golang.org/x/term v0.34.0 // indirect
|
||||||
golang.org/x/text v0.27.0 // indirect
|
golang.org/x/text v0.28.0 // indirect
|
||||||
golang.org/x/time v0.9.0 // indirect
|
golang.org/x/time v0.9.0 // indirect
|
||||||
golang.org/x/tools v0.34.0 // indirect
|
golang.org/x/tools v0.36.0 // indirect
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||||
golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
|
golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect
|
||||||
|
|||||||
+22
-22
@@ -156,8 +156,8 @@ github.com/sagernet/cors v1.2.1 h1:Cv5Z8y9YSD6Gm+qSpNrL3LO4lD3eQVvbFYJSG7JCMHQ=
|
|||||||
github.com/sagernet/cors v1.2.1/go.mod h1:O64VyOjjhrkLmQIjF4KGRrJO/5dVXFdpEmCW/eISRAI=
|
github.com/sagernet/cors v1.2.1/go.mod h1:O64VyOjjhrkLmQIjF4KGRrJO/5dVXFdpEmCW/eISRAI=
|
||||||
github.com/sagernet/fswatch v0.1.1 h1:YqID+93B7VRfqIH3PArW/XpJv5H4OLEVWDfProGoRQs=
|
github.com/sagernet/fswatch v0.1.1 h1:YqID+93B7VRfqIH3PArW/XpJv5H4OLEVWDfProGoRQs=
|
||||||
github.com/sagernet/fswatch v0.1.1/go.mod h1:nz85laH0mkQqJfaOrqPpkwtU1znMFNVTpT/5oRsVz/o=
|
github.com/sagernet/fswatch v0.1.1/go.mod h1:nz85laH0mkQqJfaOrqPpkwtU1znMFNVTpT/5oRsVz/o=
|
||||||
github.com/sagernet/gomobile v0.1.7 h1:I9jCJZTH0weP5MsuydvYHX5QfN/r6Fe8ptAIj1+SJVg=
|
github.com/sagernet/gomobile v0.1.8 h1:vXgoN0pjsMONAaYCTdsKBX2T1kxuS7sbT/mZ7PElGoo=
|
||||||
github.com/sagernet/gomobile v0.1.7/go.mod h1:Pqq2+ZVvs10U7xK+UwJgwYWUykewi8H6vlslAO73n9E=
|
github.com/sagernet/gomobile v0.1.8/go.mod h1:A8l3FlHi2D/+mfcd4HHvk5DGFPW/ShFb9jHP5VmSiDY=
|
||||||
github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb h1:pprQtDqNgqXkRsXn+0E8ikKOemzmum8bODjSfDene38=
|
github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb h1:pprQtDqNgqXkRsXn+0E8ikKOemzmum8bODjSfDene38=
|
||||||
github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb/go.mod h1:QkkPEJLw59/tfxgapHta14UL5qMUah5NXhO0Kw2Kan4=
|
github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb/go.mod h1:QkkPEJLw59/tfxgapHta14UL5qMUah5NXhO0Kw2Kan4=
|
||||||
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZNjr6sGeT00J8uU7JF4cNUdb44/Duis=
|
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZNjr6sGeT00J8uU7JF4cNUdb44/Duis=
|
||||||
@@ -167,12 +167,12 @@ github.com/sagernet/nftables v0.3.0-beta.4/go.mod h1:OQXAjvjNGGFxaTgVCSTRIhYB5/l
|
|||||||
github.com/sagernet/quic-go v0.52.0-beta.1 h1:hWkojLg64zjV+MJOvJU/kOeWndm3tiEfBLx5foisszs=
|
github.com/sagernet/quic-go v0.52.0-beta.1 h1:hWkojLg64zjV+MJOvJU/kOeWndm3tiEfBLx5foisszs=
|
||||||
github.com/sagernet/quic-go v0.52.0-beta.1/go.mod h1:OV+V5kEBb8kJS7k29MzDu6oj9GyMc7HA07sE1tedxz4=
|
github.com/sagernet/quic-go v0.52.0-beta.1/go.mod h1:OV+V5kEBb8kJS7k29MzDu6oj9GyMc7HA07sE1tedxz4=
|
||||||
github.com/sagernet/sing v0.6.9/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
github.com/sagernet/sing v0.6.9/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||||
github.com/sagernet/sing v0.7.5 h1:gNMwZCLPqR+4e0g6dwi0sSsrvOmoMjpZgqxKsuJZatc=
|
github.com/sagernet/sing v0.7.6-0.20250814022454-614cd851ca6d h1:fTGA/vTcqceUqSiXeFAO99Iiai/nWBPV+yP8tPpHPf8=
|
||||||
github.com/sagernet/sing v0.7.5/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
github.com/sagernet/sing v0.7.6-0.20250814022454-614cd851ca6d/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||||
github.com/sagernet/sing-mux v0.3.2 h1:meZVFiiStvHThb/trcpAkCrmtJOuItG5Dzl1RRP5/NE=
|
github.com/sagernet/sing-mux v0.3.3 h1:YFgt9plMWzH994BMZLmyKL37PdIVaIilwP0Jg+EcLfw=
|
||||||
github.com/sagernet/sing-mux v0.3.2/go.mod h1:pht8iFY4c9Xltj7rhVd208npkNaeCxzyXCgulDPLUDA=
|
github.com/sagernet/sing-mux v0.3.3/go.mod h1:pht8iFY4c9Xltj7rhVd208npkNaeCxzyXCgulDPLUDA=
|
||||||
github.com/sagernet/sing-quic v0.5.0-beta.3 h1:X/acRNsqQNfDlmwE7SorHfaZiny5e67hqIzM/592ric=
|
github.com/sagernet/sing-quic v0.5.0 h1:jNLIyVk24lFPvu8A4x+ZNEnZdI+Tg1rp7eCJ6v0Csak=
|
||||||
github.com/sagernet/sing-quic v0.5.0-beta.3/go.mod h1:SAv/qdeDN+75msGG5U5ZIwG+3Ua50jVIKNrRSY8pkx0=
|
github.com/sagernet/sing-quic v0.5.0/go.mod h1:SAv/qdeDN+75msGG5U5ZIwG+3Ua50jVIKNrRSY8pkx0=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.8 h1:PURj5PRoAkqeHh2ZW205RWzN9E9RtKCVCzByXruQWfE=
|
github.com/sagernet/sing-shadowsocks v0.2.8 h1:PURj5PRoAkqeHh2ZW205RWzN9E9RtKCVCzByXruQWfE=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.8/go.mod h1:lo7TWEMDcN5/h5B8S0ew+r78ZODn6SwVaFhvB6H+PTI=
|
github.com/sagernet/sing-shadowsocks v0.2.8/go.mod h1:lo7TWEMDcN5/h5B8S0ew+r78ZODn6SwVaFhvB6H+PTI=
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.2.1 h1:dWV9OXCeFPuYGHb6IRqlSptVnSzOelnqqs2gQ2/Qioo=
|
github.com/sagernet/sing-shadowsocks2 v0.2.1 h1:dWV9OXCeFPuYGHb6IRqlSptVnSzOelnqqs2gQ2/Qioo=
|
||||||
@@ -262,18 +262,18 @@ go4.org/mem v0.0.0-20240501181205-ae6ca9944745/go.mod h1:reUoABIJ9ikfM5sgtSF3Wus
|
|||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||||
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
||||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI=
|
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI=
|
||||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ=
|
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ=
|
||||||
golang.org/x/image v0.23.0 h1:HseQ7c2OpPKTPVzNjG5fwJsOTCiiwS4QdsYi5XU6H68=
|
golang.org/x/image v0.23.0 h1:HseQ7c2OpPKTPVzNjG5fwJsOTCiiwS4QdsYi5XU6H68=
|
||||||
golang.org/x/image v0.23.0/go.mod h1:wJJBTdLfCCf3tiHa1fNxpZmUI4mmoZvwMCPP0ddoNKY=
|
golang.org/x/image v0.23.0/go.mod h1:wJJBTdLfCCf3tiHa1fNxpZmUI4mmoZvwMCPP0ddoNKY=
|
||||||
golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
|
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
|
||||||
golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
|
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
@@ -285,20 +285,20 @@ golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
||||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||||
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
|
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
|
||||||
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
|
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||||
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
|||||||
@@ -100,7 +100,6 @@ func rewriteRcodeAction(rcodeMap map[string]int, ruleAction *DNSRuleAction) {
|
|||||||
}
|
}
|
||||||
ruleAction.Action = C.RuleActionTypePredefined
|
ruleAction.Action = C.RuleActionTypePredefined
|
||||||
ruleAction.PredefinedOptions.Rcode = common.Ptr(DNSRCode(rcode))
|
ruleAction.PredefinedOptions.Rcode = common.Ptr(DNSRCode(rcode))
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type DNSClientOptions struct {
|
type DNSClientOptions struct {
|
||||||
|
|||||||
+39
-36
@@ -67,42 +67,45 @@ func (r Rule) IsValid() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RawDefaultRule struct {
|
type RawDefaultRule struct {
|
||||||
Inbound badoption.Listable[string] `json:"inbound,omitempty"`
|
Inbound badoption.Listable[string] `json:"inbound,omitempty"`
|
||||||
IPVersion int `json:"ip_version,omitempty"`
|
IPVersion int `json:"ip_version,omitempty"`
|
||||||
Network badoption.Listable[string] `json:"network,omitempty"`
|
Network badoption.Listable[string] `json:"network,omitempty"`
|
||||||
AuthUser badoption.Listable[string] `json:"auth_user,omitempty"`
|
AuthUser badoption.Listable[string] `json:"auth_user,omitempty"`
|
||||||
Protocol badoption.Listable[string] `json:"protocol,omitempty"`
|
Protocol badoption.Listable[string] `json:"protocol,omitempty"`
|
||||||
Client badoption.Listable[string] `json:"client,omitempty"`
|
Client badoption.Listable[string] `json:"client,omitempty"`
|
||||||
Domain badoption.Listable[string] `json:"domain,omitempty"`
|
Domain badoption.Listable[string] `json:"domain,omitempty"`
|
||||||
DomainSuffix badoption.Listable[string] `json:"domain_suffix,omitempty"`
|
DomainSuffix badoption.Listable[string] `json:"domain_suffix,omitempty"`
|
||||||
DomainKeyword badoption.Listable[string] `json:"domain_keyword,omitempty"`
|
DomainKeyword badoption.Listable[string] `json:"domain_keyword,omitempty"`
|
||||||
DomainRegex badoption.Listable[string] `json:"domain_regex,omitempty"`
|
DomainRegex badoption.Listable[string] `json:"domain_regex,omitempty"`
|
||||||
Geosite badoption.Listable[string] `json:"geosite,omitempty"`
|
Geosite badoption.Listable[string] `json:"geosite,omitempty"`
|
||||||
SourceGeoIP badoption.Listable[string] `json:"source_geoip,omitempty"`
|
SourceGeoIP badoption.Listable[string] `json:"source_geoip,omitempty"`
|
||||||
GeoIP badoption.Listable[string] `json:"geoip,omitempty"`
|
GeoIP badoption.Listable[string] `json:"geoip,omitempty"`
|
||||||
SourceIPCIDR badoption.Listable[string] `json:"source_ip_cidr,omitempty"`
|
SourceIPCIDR badoption.Listable[string] `json:"source_ip_cidr,omitempty"`
|
||||||
SourceIPIsPrivate bool `json:"source_ip_is_private,omitempty"`
|
SourceIPIsPrivate bool `json:"source_ip_is_private,omitempty"`
|
||||||
IPCIDR badoption.Listable[string] `json:"ip_cidr,omitempty"`
|
IPCIDR badoption.Listable[string] `json:"ip_cidr,omitempty"`
|
||||||
IPIsPrivate bool `json:"ip_is_private,omitempty"`
|
IPIsPrivate bool `json:"ip_is_private,omitempty"`
|
||||||
SourcePort badoption.Listable[uint16] `json:"source_port,omitempty"`
|
SourcePort badoption.Listable[uint16] `json:"source_port,omitempty"`
|
||||||
SourcePortRange badoption.Listable[string] `json:"source_port_range,omitempty"`
|
SourcePortRange badoption.Listable[string] `json:"source_port_range,omitempty"`
|
||||||
Port badoption.Listable[uint16] `json:"port,omitempty"`
|
Port badoption.Listable[uint16] `json:"port,omitempty"`
|
||||||
PortRange badoption.Listable[string] `json:"port_range,omitempty"`
|
PortRange badoption.Listable[string] `json:"port_range,omitempty"`
|
||||||
ProcessName badoption.Listable[string] `json:"process_name,omitempty"`
|
ProcessName badoption.Listable[string] `json:"process_name,omitempty"`
|
||||||
ProcessPath badoption.Listable[string] `json:"process_path,omitempty"`
|
ProcessPath badoption.Listable[string] `json:"process_path,omitempty"`
|
||||||
ProcessPathRegex badoption.Listable[string] `json:"process_path_regex,omitempty"`
|
ProcessPathRegex badoption.Listable[string] `json:"process_path_regex,omitempty"`
|
||||||
PackageName badoption.Listable[string] `json:"package_name,omitempty"`
|
PackageName badoption.Listable[string] `json:"package_name,omitempty"`
|
||||||
User badoption.Listable[string] `json:"user,omitempty"`
|
User badoption.Listable[string] `json:"user,omitempty"`
|
||||||
UserID badoption.Listable[int32] `json:"user_id,omitempty"`
|
UserID badoption.Listable[int32] `json:"user_id,omitempty"`
|
||||||
ClashMode string `json:"clash_mode,omitempty"`
|
ClashMode string `json:"clash_mode,omitempty"`
|
||||||
NetworkType badoption.Listable[InterfaceType] `json:"network_type,omitempty"`
|
NetworkType badoption.Listable[InterfaceType] `json:"network_type,omitempty"`
|
||||||
NetworkIsExpensive bool `json:"network_is_expensive,omitempty"`
|
NetworkIsExpensive bool `json:"network_is_expensive,omitempty"`
|
||||||
NetworkIsConstrained bool `json:"network_is_constrained,omitempty"`
|
NetworkIsConstrained bool `json:"network_is_constrained,omitempty"`
|
||||||
WIFISSID badoption.Listable[string] `json:"wifi_ssid,omitempty"`
|
WIFISSID badoption.Listable[string] `json:"wifi_ssid,omitempty"`
|
||||||
WIFIBSSID badoption.Listable[string] `json:"wifi_bssid,omitempty"`
|
WIFIBSSID badoption.Listable[string] `json:"wifi_bssid,omitempty"`
|
||||||
RuleSet badoption.Listable[string] `json:"rule_set,omitempty"`
|
InterfaceAddress *badjson.TypedMap[string, badoption.Listable[badoption.Prefixable]] `json:"interface_address,omitempty"`
|
||||||
RuleSetIPCIDRMatchSource bool `json:"rule_set_ip_cidr_match_source,omitempty"`
|
NetworkInterfaceAddress *badjson.TypedMap[InterfaceType, badoption.Listable[badoption.Prefixable]] `json:"network_interface_address,omitempty"`
|
||||||
Invert bool `json:"invert,omitempty"`
|
DefaultInterfaceAddress badoption.Listable[badoption.Prefixable] `json:"default_interface_address,omitempty"`
|
||||||
|
RuleSet badoption.Listable[string] `json:"rule_set,omitempty"`
|
||||||
|
RuleSetIPCIDRMatchSource bool `json:"rule_set_ip_cidr_match_source,omitempty"`
|
||||||
|
Invert bool `json:"invert,omitempty"`
|
||||||
|
|
||||||
// Deprecated: renamed to rule_set_ip_cidr_match_source
|
// Deprecated: renamed to rule_set_ip_cidr_match_source
|
||||||
Deprecated_RulesetIPCIDRMatchSource bool `json:"rule_set_ipcidr_match_source,omitempty"`
|
Deprecated_RulesetIPCIDRMatchSource bool `json:"rule_set_ipcidr_match_source,omitempty"`
|
||||||
|
|||||||
+42
-39
@@ -68,45 +68,48 @@ func (r DNSRule) IsValid() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RawDefaultDNSRule struct {
|
type RawDefaultDNSRule struct {
|
||||||
Inbound badoption.Listable[string] `json:"inbound,omitempty"`
|
Inbound badoption.Listable[string] `json:"inbound,omitempty"`
|
||||||
IPVersion int `json:"ip_version,omitempty"`
|
IPVersion int `json:"ip_version,omitempty"`
|
||||||
QueryType badoption.Listable[DNSQueryType] `json:"query_type,omitempty"`
|
QueryType badoption.Listable[DNSQueryType] `json:"query_type,omitempty"`
|
||||||
Network badoption.Listable[string] `json:"network,omitempty"`
|
Network badoption.Listable[string] `json:"network,omitempty"`
|
||||||
AuthUser badoption.Listable[string] `json:"auth_user,omitempty"`
|
AuthUser badoption.Listable[string] `json:"auth_user,omitempty"`
|
||||||
Protocol badoption.Listable[string] `json:"protocol,omitempty"`
|
Protocol badoption.Listable[string] `json:"protocol,omitempty"`
|
||||||
Domain badoption.Listable[string] `json:"domain,omitempty"`
|
Domain badoption.Listable[string] `json:"domain,omitempty"`
|
||||||
DomainSuffix badoption.Listable[string] `json:"domain_suffix,omitempty"`
|
DomainSuffix badoption.Listable[string] `json:"domain_suffix,omitempty"`
|
||||||
DomainKeyword badoption.Listable[string] `json:"domain_keyword,omitempty"`
|
DomainKeyword badoption.Listable[string] `json:"domain_keyword,omitempty"`
|
||||||
DomainRegex badoption.Listable[string] `json:"domain_regex,omitempty"`
|
DomainRegex badoption.Listable[string] `json:"domain_regex,omitempty"`
|
||||||
Geosite badoption.Listable[string] `json:"geosite,omitempty"`
|
Geosite badoption.Listable[string] `json:"geosite,omitempty"`
|
||||||
SourceGeoIP badoption.Listable[string] `json:"source_geoip,omitempty"`
|
SourceGeoIP badoption.Listable[string] `json:"source_geoip,omitempty"`
|
||||||
GeoIP badoption.Listable[string] `json:"geoip,omitempty"`
|
GeoIP badoption.Listable[string] `json:"geoip,omitempty"`
|
||||||
IPCIDR badoption.Listable[string] `json:"ip_cidr,omitempty"`
|
IPCIDR badoption.Listable[string] `json:"ip_cidr,omitempty"`
|
||||||
IPIsPrivate bool `json:"ip_is_private,omitempty"`
|
IPIsPrivate bool `json:"ip_is_private,omitempty"`
|
||||||
IPAcceptAny bool `json:"ip_accept_any,omitempty"`
|
IPAcceptAny bool `json:"ip_accept_any,omitempty"`
|
||||||
SourceIPCIDR badoption.Listable[string] `json:"source_ip_cidr,omitempty"`
|
SourceIPCIDR badoption.Listable[string] `json:"source_ip_cidr,omitempty"`
|
||||||
SourceIPIsPrivate bool `json:"source_ip_is_private,omitempty"`
|
SourceIPIsPrivate bool `json:"source_ip_is_private,omitempty"`
|
||||||
SourcePort badoption.Listable[uint16] `json:"source_port,omitempty"`
|
SourcePort badoption.Listable[uint16] `json:"source_port,omitempty"`
|
||||||
SourcePortRange badoption.Listable[string] `json:"source_port_range,omitempty"`
|
SourcePortRange badoption.Listable[string] `json:"source_port_range,omitempty"`
|
||||||
Port badoption.Listable[uint16] `json:"port,omitempty"`
|
Port badoption.Listable[uint16] `json:"port,omitempty"`
|
||||||
PortRange badoption.Listable[string] `json:"port_range,omitempty"`
|
PortRange badoption.Listable[string] `json:"port_range,omitempty"`
|
||||||
ProcessName badoption.Listable[string] `json:"process_name,omitempty"`
|
ProcessName badoption.Listable[string] `json:"process_name,omitempty"`
|
||||||
ProcessPath badoption.Listable[string] `json:"process_path,omitempty"`
|
ProcessPath badoption.Listable[string] `json:"process_path,omitempty"`
|
||||||
ProcessPathRegex badoption.Listable[string] `json:"process_path_regex,omitempty"`
|
ProcessPathRegex badoption.Listable[string] `json:"process_path_regex,omitempty"`
|
||||||
PackageName badoption.Listable[string] `json:"package_name,omitempty"`
|
PackageName badoption.Listable[string] `json:"package_name,omitempty"`
|
||||||
User badoption.Listable[string] `json:"user,omitempty"`
|
User badoption.Listable[string] `json:"user,omitempty"`
|
||||||
UserID badoption.Listable[int32] `json:"user_id,omitempty"`
|
UserID badoption.Listable[int32] `json:"user_id,omitempty"`
|
||||||
Outbound badoption.Listable[string] `json:"outbound,omitempty"`
|
Outbound badoption.Listable[string] `json:"outbound,omitempty"`
|
||||||
ClashMode string `json:"clash_mode,omitempty"`
|
ClashMode string `json:"clash_mode,omitempty"`
|
||||||
NetworkType badoption.Listable[InterfaceType] `json:"network_type,omitempty"`
|
NetworkType badoption.Listable[InterfaceType] `json:"network_type,omitempty"`
|
||||||
NetworkIsExpensive bool `json:"network_is_expensive,omitempty"`
|
NetworkIsExpensive bool `json:"network_is_expensive,omitempty"`
|
||||||
NetworkIsConstrained bool `json:"network_is_constrained,omitempty"`
|
NetworkIsConstrained bool `json:"network_is_constrained,omitempty"`
|
||||||
WIFISSID badoption.Listable[string] `json:"wifi_ssid,omitempty"`
|
WIFISSID badoption.Listable[string] `json:"wifi_ssid,omitempty"`
|
||||||
WIFIBSSID badoption.Listable[string] `json:"wifi_bssid,omitempty"`
|
WIFIBSSID badoption.Listable[string] `json:"wifi_bssid,omitempty"`
|
||||||
RuleSet badoption.Listable[string] `json:"rule_set,omitempty"`
|
InterfaceAddress *badjson.TypedMap[string, badoption.Listable[badoption.Prefixable]] `json:"interface_address,omitempty"`
|
||||||
RuleSetIPCIDRMatchSource bool `json:"rule_set_ip_cidr_match_source,omitempty"`
|
NetworkInterfaceAddress *badjson.TypedMap[InterfaceType, badoption.Listable[badoption.Prefixable]] `json:"network_interface_address,omitempty"`
|
||||||
RuleSetIPCIDRAcceptEmpty bool `json:"rule_set_ip_cidr_accept_empty,omitempty"`
|
DefaultInterfaceAddress badoption.Listable[badoption.Prefixable] `json:"default_interface_address,omitempty"`
|
||||||
Invert bool `json:"invert,omitempty"`
|
RuleSet badoption.Listable[string] `json:"rule_set,omitempty"`
|
||||||
|
RuleSetIPCIDRMatchSource bool `json:"rule_set_ip_cidr_match_source,omitempty"`
|
||||||
|
RuleSetIPCIDRAcceptEmpty bool `json:"rule_set_ip_cidr_accept_empty,omitempty"`
|
||||||
|
Invert bool `json:"invert,omitempty"`
|
||||||
|
|
||||||
// Deprecated: renamed to rule_set_ip_cidr_match_source
|
// Deprecated: renamed to rule_set_ip_cidr_match_source
|
||||||
Deprecated_RulesetIPCIDRMatchSource bool `json:"rule_set_ipcidr_match_source,omitempty"`
|
Deprecated_RulesetIPCIDRMatchSource bool `json:"rule_set_ipcidr_match_source,omitempty"`
|
||||||
|
|||||||
+26
-23
@@ -182,28 +182,31 @@ func (r HeadlessRule) IsValid() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type DefaultHeadlessRule struct {
|
type DefaultHeadlessRule struct {
|
||||||
QueryType badoption.Listable[DNSQueryType] `json:"query_type,omitempty"`
|
QueryType badoption.Listable[DNSQueryType] `json:"query_type,omitempty"`
|
||||||
Network badoption.Listable[string] `json:"network,omitempty"`
|
Network badoption.Listable[string] `json:"network,omitempty"`
|
||||||
Domain badoption.Listable[string] `json:"domain,omitempty"`
|
Domain badoption.Listable[string] `json:"domain,omitempty"`
|
||||||
DomainSuffix badoption.Listable[string] `json:"domain_suffix,omitempty"`
|
DomainSuffix badoption.Listable[string] `json:"domain_suffix,omitempty"`
|
||||||
DomainKeyword badoption.Listable[string] `json:"domain_keyword,omitempty"`
|
DomainKeyword badoption.Listable[string] `json:"domain_keyword,omitempty"`
|
||||||
DomainRegex badoption.Listable[string] `json:"domain_regex,omitempty"`
|
DomainRegex badoption.Listable[string] `json:"domain_regex,omitempty"`
|
||||||
SourceIPCIDR badoption.Listable[string] `json:"source_ip_cidr,omitempty"`
|
SourceIPCIDR badoption.Listable[string] `json:"source_ip_cidr,omitempty"`
|
||||||
IPCIDR badoption.Listable[string] `json:"ip_cidr,omitempty"`
|
IPCIDR badoption.Listable[string] `json:"ip_cidr,omitempty"`
|
||||||
SourcePort badoption.Listable[uint16] `json:"source_port,omitempty"`
|
SourcePort badoption.Listable[uint16] `json:"source_port,omitempty"`
|
||||||
SourcePortRange badoption.Listable[string] `json:"source_port_range,omitempty"`
|
SourcePortRange badoption.Listable[string] `json:"source_port_range,omitempty"`
|
||||||
Port badoption.Listable[uint16] `json:"port,omitempty"`
|
Port badoption.Listable[uint16] `json:"port,omitempty"`
|
||||||
PortRange badoption.Listable[string] `json:"port_range,omitempty"`
|
PortRange badoption.Listable[string] `json:"port_range,omitempty"`
|
||||||
ProcessName badoption.Listable[string] `json:"process_name,omitempty"`
|
ProcessName badoption.Listable[string] `json:"process_name,omitempty"`
|
||||||
ProcessPath badoption.Listable[string] `json:"process_path,omitempty"`
|
ProcessPath badoption.Listable[string] `json:"process_path,omitempty"`
|
||||||
ProcessPathRegex badoption.Listable[string] `json:"process_path_regex,omitempty"`
|
ProcessPathRegex badoption.Listable[string] `json:"process_path_regex,omitempty"`
|
||||||
PackageName badoption.Listable[string] `json:"package_name,omitempty"`
|
PackageName badoption.Listable[string] `json:"package_name,omitempty"`
|
||||||
NetworkType badoption.Listable[InterfaceType] `json:"network_type,omitempty"`
|
NetworkType badoption.Listable[InterfaceType] `json:"network_type,omitempty"`
|
||||||
NetworkIsExpensive bool `json:"network_is_expensive,omitempty"`
|
NetworkIsExpensive bool `json:"network_is_expensive,omitempty"`
|
||||||
NetworkIsConstrained bool `json:"network_is_constrained,omitempty"`
|
NetworkIsConstrained bool `json:"network_is_constrained,omitempty"`
|
||||||
WIFISSID badoption.Listable[string] `json:"wifi_ssid,omitempty"`
|
WIFISSID badoption.Listable[string] `json:"wifi_ssid,omitempty"`
|
||||||
WIFIBSSID badoption.Listable[string] `json:"wifi_bssid,omitempty"`
|
WIFIBSSID badoption.Listable[string] `json:"wifi_bssid,omitempty"`
|
||||||
Invert bool `json:"invert,omitempty"`
|
NetworkInterfaceAddress *badjson.TypedMap[InterfaceType, badoption.Listable[badoption.Prefixable]] `json:"network_interface_address,omitempty"`
|
||||||
|
DefaultInterfaceAddress badoption.Listable[badoption.Prefixable] `json:"default_interface_address,omitempty"`
|
||||||
|
|
||||||
|
Invert bool `json:"invert,omitempty"`
|
||||||
|
|
||||||
DomainMatcher *domain.Matcher `json:"-"`
|
DomainMatcher *domain.Matcher `json:"-"`
|
||||||
SourceIPSet *netipx.IPSet `json:"-"`
|
SourceIPSet *netipx.IPSet `json:"-"`
|
||||||
@@ -240,7 +243,7 @@ type PlainRuleSetCompat _PlainRuleSetCompat
|
|||||||
func (r PlainRuleSetCompat) MarshalJSON() ([]byte, error) {
|
func (r PlainRuleSetCompat) MarshalJSON() ([]byte, error) {
|
||||||
var v any
|
var v any
|
||||||
switch r.Version {
|
switch r.Version {
|
||||||
case C.RuleSetVersion1, C.RuleSetVersion2, C.RuleSetVersion3:
|
case C.RuleSetVersion1, C.RuleSetVersion2, C.RuleSetVersion3, C.RuleSetVersion4:
|
||||||
v = r.Options
|
v = r.Options
|
||||||
default:
|
default:
|
||||||
return nil, E.New("unknown rule-set version: ", r.Version)
|
return nil, E.New("unknown rule-set version: ", r.Version)
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ func RegisterOutbound(registry *outbound.Registry) {
|
|||||||
|
|
||||||
type Outbound struct {
|
type Outbound struct {
|
||||||
outbound.Adapter
|
outbound.Adapter
|
||||||
dialer N.Dialer
|
dialer tls.Dialer
|
||||||
server M.Socksaddr
|
server M.Socksaddr
|
||||||
tlsConfig tls.Config
|
tlsConfig tls.Config
|
||||||
client *anytls.Client
|
client *anytls.Client
|
||||||
@@ -58,7 +58,8 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
outbound.dialer = outboundDialer
|
|
||||||
|
outbound.dialer = tls.NewDialer(outboundDialer, tlsConfig)
|
||||||
|
|
||||||
client, err := anytls.NewClient(ctx, anytls.ClientConfig{
|
client, err := anytls.NewClient(ctx, anytls.ClientConfig{
|
||||||
Password: options.Password,
|
Password: options.Password,
|
||||||
@@ -91,16 +92,7 @@ func (d anytlsDialer) ListenPacket(ctx context.Context, destination M.Socksaddr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *Outbound) dialOut(ctx context.Context) (net.Conn, error) {
|
func (h *Outbound) dialOut(ctx context.Context) (net.Conn, error) {
|
||||||
conn, err := h.dialer.DialContext(ctx, N.NetworkTCP, h.server)
|
return h.dialer.DialTLSContext(ctx, h.server)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
tlsConn, err := tls.ClientHandshake(ctx, conn, h.tlsConfig)
|
|
||||||
if err != nil {
|
|
||||||
common.Close(tlsConn, conn)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return tlsConn, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Outbound) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
func (h *Outbound) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||||
|
|||||||
@@ -313,7 +313,7 @@ func (g *URLTestGroup) Select(network string) (adapter.Outbound, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *URLTestGroup) loopCheck() {
|
func (g *URLTestGroup) loopCheck() {
|
||||||
if time.Now().Sub(g.lastActive.Load()) > g.interval {
|
if time.Since(g.lastActive.Load()) > g.interval {
|
||||||
g.lastActive.Store(time.Now())
|
g.lastActive.Store(time.Now())
|
||||||
g.CheckOutbounds(false)
|
g.CheckOutbounds(false)
|
||||||
}
|
}
|
||||||
@@ -323,7 +323,7 @@ func (g *URLTestGroup) loopCheck() {
|
|||||||
return
|
return
|
||||||
case <-g.ticker.C:
|
case <-g.ticker.C:
|
||||||
}
|
}
|
||||||
if time.Now().Sub(g.lastActive.Load()) > g.idleTimeout {
|
if time.Since(g.lastActive.Load()) > g.idleTimeout {
|
||||||
g.access.Lock()
|
g.access.Lock()
|
||||||
g.ticker.Stop()
|
g.ticker.Stop()
|
||||||
g.ticker = nil
|
g.ticker = nil
|
||||||
@@ -360,7 +360,7 @@ func (g *URLTestGroup) urlTest(ctx context.Context, force bool) (map[string]uint
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
history := g.history.LoadURLTestHistory(realTag)
|
history := g.history.LoadURLTestHistory(realTag)
|
||||||
if !force && history != nil && time.Now().Sub(history.Time) < g.interval {
|
if !force && history != nil && time.Since(history.Time) < g.interval {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
checked[realTag] = true
|
checked[realTag] = true
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
detour, err := tls.NewDialerFromOptions(ctx, router, outboundDialer, options.Server, common.PtrValueOrDefault(options.TLS))
|
detour, err := tls.NewDialerFromOptions(ctx, outboundDialer, options.Server, common.PtrValueOrDefault(options.TLS))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,7 +128,6 @@ func (h *Outbound) InterfaceUpdated() {
|
|||||||
if h.multiplexDialer != nil {
|
if h.multiplexDialer != nil {
|
||||||
h.multiplexDialer.Reset()
|
h.multiplexDialer.Reset()
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Outbound) Close() error {
|
func (h *Outbound) Close() error {
|
||||||
|
|||||||
@@ -180,7 +180,6 @@ func (s *Outbound) connect() (*ssh.Client, error) {
|
|||||||
|
|
||||||
func (s *Outbound) InterfaceUpdated() {
|
func (s *Outbound) InterfaceUpdated() {
|
||||||
common.Close(s.clientConn)
|
common.Close(s.clientConn)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Outbound) Close() error {
|
func (s *Outbound) Close() error {
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ type Outbound struct {
|
|||||||
key [56]byte
|
key [56]byte
|
||||||
multiplexDialer *mux.Client
|
multiplexDialer *mux.Client
|
||||||
tlsConfig tls.Config
|
tlsConfig tls.Config
|
||||||
|
tlsDialer tls.Dialer
|
||||||
transport adapter.V2RayClientTransport
|
transport adapter.V2RayClientTransport
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,6 +55,7 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
outbound.tlsDialer = tls.NewDialer(outboundDialer, outbound.tlsConfig)
|
||||||
}
|
}
|
||||||
if options.Transport != nil {
|
if options.Transport != nil {
|
||||||
outbound.transport, err = v2ray.NewClientTransport(ctx, outbound.dialer, outbound.serverAddr, common.PtrValueOrDefault(options.Transport), outbound.tlsConfig)
|
outbound.transport, err = v2ray.NewClientTransport(ctx, outbound.dialer, outbound.serverAddr, common.PtrValueOrDefault(options.Transport), outbound.tlsConfig)
|
||||||
@@ -105,7 +107,6 @@ func (h *Outbound) InterfaceUpdated() {
|
|||||||
if h.multiplexDialer != nil {
|
if h.multiplexDialer != nil {
|
||||||
h.multiplexDialer.Reset()
|
h.multiplexDialer.Reset()
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Outbound) Close() error {
|
func (h *Outbound) Close() error {
|
||||||
@@ -122,11 +123,10 @@ func (h *trojanDialer) DialContext(ctx context.Context, network string, destinat
|
|||||||
var err error
|
var err error
|
||||||
if h.transport != nil {
|
if h.transport != nil {
|
||||||
conn, err = h.transport.DialContext(ctx)
|
conn, err = h.transport.DialContext(ctx)
|
||||||
|
} else if h.tlsDialer != nil {
|
||||||
|
conn, err = h.tlsDialer.DialTLSContext(ctx, h.serverAddr)
|
||||||
} else {
|
} else {
|
||||||
conn, err = h.dialer.DialContext(ctx, N.NetworkTCP, h.serverAddr)
|
conn, err = h.dialer.DialContext(ctx, N.NetworkTCP, h.serverAddr)
|
||||||
if err == nil && h.tlsConfig != nil {
|
|
||||||
conn, err = tls.ClientHandshake(ctx, conn, h.tlsConfig)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.Close(conn)
|
common.Close(conn)
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ type Outbound struct {
|
|||||||
serverAddr M.Socksaddr
|
serverAddr M.Socksaddr
|
||||||
multiplexDialer *mux.Client
|
multiplexDialer *mux.Client
|
||||||
tlsConfig tls.Config
|
tlsConfig tls.Config
|
||||||
|
tlsDialer tls.Dialer
|
||||||
transport adapter.V2RayClientTransport
|
transport adapter.V2RayClientTransport
|
||||||
packetAddr bool
|
packetAddr bool
|
||||||
xudp bool
|
xudp bool
|
||||||
@@ -56,6 +57,7 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
outbound.tlsDialer = tls.NewDialer(outboundDialer, outbound.tlsConfig)
|
||||||
}
|
}
|
||||||
if options.Transport != nil {
|
if options.Transport != nil {
|
||||||
outbound.transport, err = v2ray.NewClientTransport(ctx, outbound.dialer, outbound.serverAddr, common.PtrValueOrDefault(options.Transport), outbound.tlsConfig)
|
outbound.transport, err = v2ray.NewClientTransport(ctx, outbound.dialer, outbound.serverAddr, common.PtrValueOrDefault(options.Transport), outbound.tlsConfig)
|
||||||
@@ -124,7 +126,6 @@ func (h *Outbound) InterfaceUpdated() {
|
|||||||
if h.multiplexDialer != nil {
|
if h.multiplexDialer != nil {
|
||||||
h.multiplexDialer.Reset()
|
h.multiplexDialer.Reset()
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Outbound) Close() error {
|
func (h *Outbound) Close() error {
|
||||||
@@ -141,11 +142,10 @@ func (h *vlessDialer) DialContext(ctx context.Context, network string, destinati
|
|||||||
var err error
|
var err error
|
||||||
if h.transport != nil {
|
if h.transport != nil {
|
||||||
conn, err = h.transport.DialContext(ctx)
|
conn, err = h.transport.DialContext(ctx)
|
||||||
|
} else if h.tlsDialer != nil {
|
||||||
|
conn, err = h.tlsDialer.DialTLSContext(ctx, h.serverAddr)
|
||||||
} else {
|
} else {
|
||||||
conn, err = h.dialer.DialContext(ctx, N.NetworkTCP, h.serverAddr)
|
conn, err = h.dialer.DialContext(ctx, N.NetworkTCP, h.serverAddr)
|
||||||
if err == nil && h.tlsConfig != nil {
|
|
||||||
conn, err = tls.ClientHandshake(ctx, conn, h.tlsConfig)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -184,11 +184,10 @@ func (h *vlessDialer) ListenPacket(ctx context.Context, destination M.Socksaddr)
|
|||||||
var err error
|
var err error
|
||||||
if h.transport != nil {
|
if h.transport != nil {
|
||||||
conn, err = h.transport.DialContext(ctx)
|
conn, err = h.transport.DialContext(ctx)
|
||||||
|
} else if h.tlsDialer != nil {
|
||||||
|
conn, err = h.tlsDialer.DialTLSContext(ctx, h.serverAddr)
|
||||||
} else {
|
} else {
|
||||||
conn, err = h.dialer.DialContext(ctx, N.NetworkTCP, h.serverAddr)
|
conn, err = h.dialer.DialContext(ctx, N.NetworkTCP, h.serverAddr)
|
||||||
if err == nil && h.tlsConfig != nil {
|
|
||||||
conn, err = tls.ClientHandshake(ctx, conn, h.tlsConfig)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.Close(conn)
|
common.Close(conn)
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ type Outbound struct {
|
|||||||
serverAddr M.Socksaddr
|
serverAddr M.Socksaddr
|
||||||
multiplexDialer *mux.Client
|
multiplexDialer *mux.Client
|
||||||
tlsConfig tls.Config
|
tlsConfig tls.Config
|
||||||
|
tlsDialer tls.Dialer
|
||||||
transport adapter.V2RayClientTransport
|
transport adapter.V2RayClientTransport
|
||||||
packetAddr bool
|
packetAddr bool
|
||||||
xudp bool
|
xudp bool
|
||||||
@@ -56,6 +57,7 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
outbound.tlsDialer = tls.NewDialer(outboundDialer, outbound.tlsConfig)
|
||||||
}
|
}
|
||||||
if options.Transport != nil {
|
if options.Transport != nil {
|
||||||
outbound.transport, err = v2ray.NewClientTransport(ctx, outbound.dialer, outbound.serverAddr, common.PtrValueOrDefault(options.Transport), outbound.tlsConfig)
|
outbound.transport, err = v2ray.NewClientTransport(ctx, outbound.dialer, outbound.serverAddr, common.PtrValueOrDefault(options.Transport), outbound.tlsConfig)
|
||||||
@@ -108,7 +110,6 @@ func (h *Outbound) InterfaceUpdated() {
|
|||||||
if h.multiplexDialer != nil {
|
if h.multiplexDialer != nil {
|
||||||
h.multiplexDialer.Reset()
|
h.multiplexDialer.Reset()
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Outbound) Close() error {
|
func (h *Outbound) Close() error {
|
||||||
@@ -155,11 +156,10 @@ func (h *vmessDialer) DialContext(ctx context.Context, network string, destinati
|
|||||||
var err error
|
var err error
|
||||||
if h.transport != nil {
|
if h.transport != nil {
|
||||||
conn, err = h.transport.DialContext(ctx)
|
conn, err = h.transport.DialContext(ctx)
|
||||||
|
} else if h.tlsDialer != nil {
|
||||||
|
conn, err = h.tlsDialer.DialTLSContext(ctx, h.serverAddr)
|
||||||
} else {
|
} else {
|
||||||
conn, err = h.dialer.DialContext(ctx, N.NetworkTCP, h.serverAddr)
|
conn, err = h.dialer.DialContext(ctx, N.NetworkTCP, h.serverAddr)
|
||||||
if err == nil && h.tlsConfig != nil {
|
|
||||||
conn, err = tls.ClientHandshake(ctx, conn, h.tlsConfig)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.Close(conn)
|
common.Close(conn)
|
||||||
@@ -183,11 +183,10 @@ func (h *vmessDialer) ListenPacket(ctx context.Context, destination M.Socksaddr)
|
|||||||
var err error
|
var err error
|
||||||
if h.transport != nil {
|
if h.transport != nil {
|
||||||
conn, err = h.transport.DialContext(ctx)
|
conn, err = h.transport.DialContext(ctx)
|
||||||
|
} else if h.tlsDialer != nil {
|
||||||
|
conn, err = h.tlsDialer.DialTLSContext(ctx, h.serverAddr)
|
||||||
} else {
|
} else {
|
||||||
conn, err = h.dialer.DialContext(ctx, N.NetworkTCP, h.serverAddr)
|
conn, err = h.dialer.DialContext(ctx, N.NetworkTCP, h.serverAddr)
|
||||||
if err == nil && h.tlsConfig != nil {
|
|
||||||
conn, err = tls.ClientHandshake(ctx, conn, h.tlsConfig)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -246,6 +246,21 @@ func NewDefaultRule(ctx context.Context, logger log.ContextLogger, options optio
|
|||||||
rule.items = append(rule.items, item)
|
rule.items = append(rule.items, item)
|
||||||
rule.allItems = append(rule.allItems, item)
|
rule.allItems = append(rule.allItems, item)
|
||||||
}
|
}
|
||||||
|
if options.InterfaceAddress != nil && options.InterfaceAddress.Size() > 0 {
|
||||||
|
item := NewInterfaceAddressItem(networkManager, options.InterfaceAddress)
|
||||||
|
rule.items = append(rule.items, item)
|
||||||
|
rule.allItems = append(rule.allItems, item)
|
||||||
|
}
|
||||||
|
if options.NetworkInterfaceAddress != nil && options.NetworkInterfaceAddress.Size() > 0 {
|
||||||
|
item := NewNetworkInterfaceAddressItem(networkManager, options.NetworkInterfaceAddress)
|
||||||
|
rule.items = append(rule.items, item)
|
||||||
|
rule.allItems = append(rule.allItems, item)
|
||||||
|
}
|
||||||
|
if len(options.DefaultInterfaceAddress) > 0 {
|
||||||
|
item := NewDefaultInterfaceAddressItem(networkManager, options.DefaultInterfaceAddress)
|
||||||
|
rule.items = append(rule.items, item)
|
||||||
|
rule.allItems = append(rule.allItems, item)
|
||||||
|
}
|
||||||
if len(options.RuleSet) > 0 {
|
if len(options.RuleSet) > 0 {
|
||||||
var matchSource bool
|
var matchSource bool
|
||||||
if options.RuleSetIPCIDRMatchSource {
|
if options.RuleSetIPCIDRMatchSource {
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package rule
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/netip"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-tun"
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
|
"github.com/sagernet/sing/common/json/badoption"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ RuleItem = (*DefaultInterfaceAddressItem)(nil)
|
||||||
|
|
||||||
|
type DefaultInterfaceAddressItem struct {
|
||||||
|
interfaceMonitor tun.DefaultInterfaceMonitor
|
||||||
|
interfaceAddresses []netip.Prefix
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDefaultInterfaceAddressItem(networkManager adapter.NetworkManager, interfaceAddresses badoption.Listable[badoption.Prefixable]) *DefaultInterfaceAddressItem {
|
||||||
|
item := &DefaultInterfaceAddressItem{
|
||||||
|
interfaceMonitor: networkManager.InterfaceMonitor(),
|
||||||
|
interfaceAddresses: make([]netip.Prefix, 0, len(interfaceAddresses)),
|
||||||
|
}
|
||||||
|
for _, prefixable := range interfaceAddresses {
|
||||||
|
item.interfaceAddresses = append(item.interfaceAddresses, prefixable.Build(netip.Prefix{}))
|
||||||
|
}
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *DefaultInterfaceAddressItem) Match(metadata *adapter.InboundContext) bool {
|
||||||
|
defaultInterface := r.interfaceMonitor.DefaultInterface()
|
||||||
|
if defaultInterface == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, address := range r.interfaceAddresses {
|
||||||
|
if common.All(defaultInterface.Addresses, func(it netip.Prefix) bool {
|
||||||
|
return !address.Overlaps(it)
|
||||||
|
}) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *DefaultInterfaceAddressItem) String() string {
|
||||||
|
addressLen := len(r.interfaceAddresses)
|
||||||
|
switch {
|
||||||
|
case addressLen == 1:
|
||||||
|
return "default_interface_address=" + r.interfaceAddresses[0].String()
|
||||||
|
case addressLen > 3:
|
||||||
|
return "default_interface_address=[" + strings.Join(common.Map(r.interfaceAddresses[:3], netip.Prefix.String), " ") + "...]"
|
||||||
|
default:
|
||||||
|
return "default_interface_address=[" + strings.Join(common.Map(r.interfaceAddresses, netip.Prefix.String), " ") + "]"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -247,6 +247,21 @@ func NewDefaultDNSRule(ctx context.Context, logger log.ContextLogger, options op
|
|||||||
rule.items = append(rule.items, item)
|
rule.items = append(rule.items, item)
|
||||||
rule.allItems = append(rule.allItems, item)
|
rule.allItems = append(rule.allItems, item)
|
||||||
}
|
}
|
||||||
|
if options.InterfaceAddress != nil && options.InterfaceAddress.Size() > 0 {
|
||||||
|
item := NewInterfaceAddressItem(networkManager, options.InterfaceAddress)
|
||||||
|
rule.items = append(rule.items, item)
|
||||||
|
rule.allItems = append(rule.allItems, item)
|
||||||
|
}
|
||||||
|
if options.NetworkInterfaceAddress != nil && options.NetworkInterfaceAddress.Size() > 0 {
|
||||||
|
item := NewNetworkInterfaceAddressItem(networkManager, options.NetworkInterfaceAddress)
|
||||||
|
rule.items = append(rule.items, item)
|
||||||
|
rule.allItems = append(rule.allItems, item)
|
||||||
|
}
|
||||||
|
if len(options.DefaultInterfaceAddress) > 0 {
|
||||||
|
item := NewDefaultInterfaceAddressItem(networkManager, options.DefaultInterfaceAddress)
|
||||||
|
rule.items = append(rule.items, item)
|
||||||
|
rule.allItems = append(rule.allItems, item)
|
||||||
|
}
|
||||||
if len(options.RuleSet) > 0 {
|
if len(options.RuleSet) > 0 {
|
||||||
var matchSource bool
|
var matchSource bool
|
||||||
if options.RuleSetIPCIDRMatchSource {
|
if options.RuleSetIPCIDRMatchSource {
|
||||||
|
|||||||
@@ -164,13 +164,21 @@ func NewDefaultHeadlessRule(ctx context.Context, options option.DefaultHeadlessR
|
|||||||
item := NewWIFISSIDItem(networkManager, options.WIFISSID)
|
item := NewWIFISSIDItem(networkManager, options.WIFISSID)
|
||||||
rule.items = append(rule.items, item)
|
rule.items = append(rule.items, item)
|
||||||
rule.allItems = append(rule.allItems, item)
|
rule.allItems = append(rule.allItems, item)
|
||||||
|
|
||||||
}
|
}
|
||||||
if len(options.WIFIBSSID) > 0 {
|
if len(options.WIFIBSSID) > 0 {
|
||||||
item := NewWIFIBSSIDItem(networkManager, options.WIFIBSSID)
|
item := NewWIFIBSSIDItem(networkManager, options.WIFIBSSID)
|
||||||
rule.items = append(rule.items, item)
|
rule.items = append(rule.items, item)
|
||||||
rule.allItems = append(rule.allItems, item)
|
rule.allItems = append(rule.allItems, item)
|
||||||
|
}
|
||||||
|
if options.NetworkInterfaceAddress != nil && options.NetworkInterfaceAddress.Size() > 0 {
|
||||||
|
item := NewNetworkInterfaceAddressItem(networkManager, options.NetworkInterfaceAddress)
|
||||||
|
rule.items = append(rule.items, item)
|
||||||
|
rule.allItems = append(rule.allItems, item)
|
||||||
|
}
|
||||||
|
if len(options.DefaultInterfaceAddress) > 0 {
|
||||||
|
item := NewDefaultInterfaceAddressItem(networkManager, options.DefaultInterfaceAddress)
|
||||||
|
rule.items = append(rule.items, item)
|
||||||
|
rule.allItems = append(rule.allItems, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(options.AdGuardDomain) > 0 {
|
if len(options.AdGuardDomain) > 0 {
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package rule
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/netip"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
|
"github.com/sagernet/sing/common/control"
|
||||||
|
"github.com/sagernet/sing/common/json/badjson"
|
||||||
|
"github.com/sagernet/sing/common/json/badoption"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ RuleItem = (*InterfaceAddressItem)(nil)
|
||||||
|
|
||||||
|
type InterfaceAddressItem struct {
|
||||||
|
networkManager adapter.NetworkManager
|
||||||
|
interfaceAddresses map[string][]netip.Prefix
|
||||||
|
description string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewInterfaceAddressItem(networkManager adapter.NetworkManager, interfaceAddresses *badjson.TypedMap[string, badoption.Listable[badoption.Prefixable]]) *InterfaceAddressItem {
|
||||||
|
item := &InterfaceAddressItem{
|
||||||
|
networkManager: networkManager,
|
||||||
|
interfaceAddresses: make(map[string][]netip.Prefix, interfaceAddresses.Size()),
|
||||||
|
}
|
||||||
|
var entryDescriptions []string
|
||||||
|
for _, entry := range interfaceAddresses.Entries() {
|
||||||
|
prefixes := make([]netip.Prefix, 0, len(entry.Value))
|
||||||
|
for _, prefixable := range entry.Value {
|
||||||
|
prefixes = append(prefixes, prefixable.Build(netip.Prefix{}))
|
||||||
|
}
|
||||||
|
item.interfaceAddresses[entry.Key] = prefixes
|
||||||
|
entryDescriptions = append(entryDescriptions, entry.Key+"="+strings.Join(common.Map(prefixes, netip.Prefix.String), ","))
|
||||||
|
}
|
||||||
|
item.description = "interface_address=[" + strings.Join(entryDescriptions, " ") + "]"
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *InterfaceAddressItem) Match(metadata *adapter.InboundContext) bool {
|
||||||
|
interfaces := r.networkManager.InterfaceFinder().Interfaces()
|
||||||
|
for ifName, addresses := range r.interfaceAddresses {
|
||||||
|
iface := common.Find(interfaces, func(it control.Interface) bool {
|
||||||
|
return it.Name == ifName
|
||||||
|
})
|
||||||
|
if iface.Name == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if common.All(addresses, func(address netip.Prefix) bool {
|
||||||
|
return common.All(iface.Addresses, func(it netip.Prefix) bool {
|
||||||
|
return !address.Overlaps(it)
|
||||||
|
})
|
||||||
|
}) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *InterfaceAddressItem) String() string {
|
||||||
|
return r.description
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package rule
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/netip"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
C "github.com/sagernet/sing-box/constant"
|
||||||
|
"github.com/sagernet/sing-box/option"
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
|
"github.com/sagernet/sing/common/json/badjson"
|
||||||
|
"github.com/sagernet/sing/common/json/badoption"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ RuleItem = (*NetworkInterfaceAddressItem)(nil)
|
||||||
|
|
||||||
|
type NetworkInterfaceAddressItem struct {
|
||||||
|
networkManager adapter.NetworkManager
|
||||||
|
interfaceAddresses map[C.InterfaceType][]netip.Prefix
|
||||||
|
description string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewNetworkInterfaceAddressItem(networkManager adapter.NetworkManager, interfaceAddresses *badjson.TypedMap[option.InterfaceType, badoption.Listable[badoption.Prefixable]]) *NetworkInterfaceAddressItem {
|
||||||
|
item := &NetworkInterfaceAddressItem{
|
||||||
|
networkManager: networkManager,
|
||||||
|
interfaceAddresses: make(map[C.InterfaceType][]netip.Prefix, interfaceAddresses.Size()),
|
||||||
|
}
|
||||||
|
var entryDescriptions []string
|
||||||
|
for _, entry := range interfaceAddresses.Entries() {
|
||||||
|
prefixes := make([]netip.Prefix, 0, len(entry.Value))
|
||||||
|
for _, prefixable := range entry.Value {
|
||||||
|
prefixes = append(prefixes, prefixable.Build(netip.Prefix{}))
|
||||||
|
}
|
||||||
|
item.interfaceAddresses[entry.Key.Build()] = prefixes
|
||||||
|
entryDescriptions = append(entryDescriptions, entry.Key.Build().String()+"="+strings.Join(common.Map(prefixes, netip.Prefix.String), ","))
|
||||||
|
}
|
||||||
|
item.description = "network_interface_address=[" + strings.Join(entryDescriptions, " ") + "]"
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *NetworkInterfaceAddressItem) Match(metadata *adapter.InboundContext) bool {
|
||||||
|
interfaces := r.networkManager.NetworkInterfaces()
|
||||||
|
match:
|
||||||
|
for ifType, addresses := range r.interfaceAddresses {
|
||||||
|
for _, networkInterface := range interfaces {
|
||||||
|
if networkInterface.Type != ifType {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if common.Any(networkInterface.Addresses, func(it netip.Prefix) bool {
|
||||||
|
return common.Any(addresses, func(prefix netip.Prefix) bool {
|
||||||
|
return prefix.Overlaps(it)
|
||||||
|
})
|
||||||
|
}) {
|
||||||
|
continue match
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *NetworkInterfaceAddressItem) String() string {
|
||||||
|
return r.description
|
||||||
|
}
|
||||||
@@ -42,7 +42,7 @@ func extractIPSetFromRule(rawRule adapter.HeadlessRule) []*netipx.IPSet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasHeadlessRule(rules []option.HeadlessRule, cond func(rule option.DefaultHeadlessRule) bool) bool {
|
func HasHeadlessRule(rules []option.HeadlessRule, cond func(rule option.DefaultHeadlessRule) bool) bool {
|
||||||
for _, rule := range rules {
|
for _, rule := range rules {
|
||||||
switch rule.Type {
|
switch rule.Type {
|
||||||
case C.RuleTypeDefault:
|
case C.RuleTypeDefault:
|
||||||
@@ -50,7 +50,7 @@ func hasHeadlessRule(rules []option.HeadlessRule, cond func(rule option.DefaultH
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
case C.RuleTypeLogical:
|
case C.RuleTypeLogical:
|
||||||
if hasHeadlessRule(rule.LogicalOptions.Rules, cond) {
|
if HasHeadlessRule(rule.LogicalOptions.Rules, cond) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -138,9 +138,9 @@ func (s *LocalRuleSet) reloadRules(headlessRules []option.HeadlessRule) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
var metadata adapter.RuleSetMetadata
|
var metadata adapter.RuleSetMetadata
|
||||||
metadata.ContainsProcessRule = hasHeadlessRule(headlessRules, isProcessHeadlessRule)
|
metadata.ContainsProcessRule = HasHeadlessRule(headlessRules, isProcessHeadlessRule)
|
||||||
metadata.ContainsWIFIRule = hasHeadlessRule(headlessRules, isWIFIHeadlessRule)
|
metadata.ContainsWIFIRule = HasHeadlessRule(headlessRules, isWIFIHeadlessRule)
|
||||||
metadata.ContainsIPCIDRRule = hasHeadlessRule(headlessRules, isIPCIDRHeadlessRule)
|
metadata.ContainsIPCIDRRule = HasHeadlessRule(headlessRules, isIPCIDRHeadlessRule)
|
||||||
s.rules = rules
|
s.rules = rules
|
||||||
s.metadata = metadata
|
s.metadata = metadata
|
||||||
s.callbackAccess.Lock()
|
s.callbackAccess.Lock()
|
||||||
|
|||||||
@@ -185,9 +185,9 @@ func (s *RemoteRuleSet) loadBytes(content []byte) error {
|
|||||||
return E.Cause(err, "parse rule_set.rules.[", i, "]")
|
return E.Cause(err, "parse rule_set.rules.[", i, "]")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.metadata.ContainsProcessRule = hasHeadlessRule(plainRuleSet.Rules, isProcessHeadlessRule)
|
s.metadata.ContainsProcessRule = HasHeadlessRule(plainRuleSet.Rules, isProcessHeadlessRule)
|
||||||
s.metadata.ContainsWIFIRule = hasHeadlessRule(plainRuleSet.Rules, isWIFIHeadlessRule)
|
s.metadata.ContainsWIFIRule = HasHeadlessRule(plainRuleSet.Rules, isWIFIHeadlessRule)
|
||||||
s.metadata.ContainsIPCIDRRule = hasHeadlessRule(plainRuleSet.Rules, isIPCIDRHeadlessRule)
|
s.metadata.ContainsIPCIDRRule = HasHeadlessRule(plainRuleSet.Rules, isIPCIDRHeadlessRule)
|
||||||
s.rules = rules
|
s.rules = rules
|
||||||
s.callbackAccess.Lock()
|
s.callbackAccess.Lock()
|
||||||
callbacks := s.callbacks.Array()
|
callbacks := s.callbacks.Array()
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package ssmapi
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing/common/logger"
|
"github.com/sagernet/sing/common/logger"
|
||||||
@@ -157,18 +156,14 @@ func (s *APIServer) deleteUser(writer http.ResponseWriter, request *http.Request
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *APIServer) getStats(writer http.ResponseWriter, request *http.Request) {
|
func (s *APIServer) getStats(writer http.ResponseWriter, request *http.Request) {
|
||||||
requireClear, _ := strconv.ParseBool(chi.URLParam(request, "clear"))
|
requireClear := request.URL.Query().Get("clear") == "true"
|
||||||
|
|
||||||
users := s.user.List()
|
users := s.user.List()
|
||||||
s.traffic.ReadUsers(users)
|
s.traffic.ReadUsers(users, requireClear)
|
||||||
for i := range users {
|
for i := range users {
|
||||||
users[i].Password = ""
|
users[i].Password = ""
|
||||||
}
|
}
|
||||||
uplinkBytes, downlinkBytes, uplinkPackets, downlinkPackets, tcpSessions, udpSessions := s.traffic.ReadGlobal()
|
uplinkBytes, downlinkBytes, uplinkPackets, downlinkPackets, tcpSessions, udpSessions := s.traffic.ReadGlobal(requireClear)
|
||||||
|
|
||||||
if requireClear {
|
|
||||||
s.traffic.Clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
render.JSON(writer, request, render.M{
|
render.JSON(writer, request, render.M{
|
||||||
"uplinkBytes": uplinkBytes,
|
"uplinkBytes": uplinkBytes,
|
||||||
|
|||||||
@@ -142,86 +142,82 @@ func (s *TrafficManager) TrackPacketConnection(conn N.PacketConn, metadata adapt
|
|||||||
readPacketCounter = append(readPacketCounter, upPacketsCounter)
|
readPacketCounter = append(readPacketCounter, upPacketsCounter)
|
||||||
writePacketCounter = append(writePacketCounter, downPacketsCounter)
|
writePacketCounter = append(writePacketCounter, downPacketsCounter)
|
||||||
udpSessionCounter.Add(1)
|
udpSessionCounter.Add(1)
|
||||||
return bufio.NewInt64CounterPacketConn(conn, append(readCounter, readPacketCounter...), append(writeCounter, writePacketCounter...))
|
return bufio.NewInt64CounterPacketConn(conn, readCounter, readPacketCounter, writeCounter, writePacketCounter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TrafficManager) ReadUser(user *UserObject) {
|
func (s *TrafficManager) ReadUser(user *UserObject) {
|
||||||
s.userAccess.Lock()
|
s.userAccess.Lock()
|
||||||
defer s.userAccess.Unlock()
|
defer s.userAccess.Unlock()
|
||||||
s.readUser(user)
|
s.readUser(user, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TrafficManager) readUser(user *UserObject) {
|
func (s *TrafficManager) readUser(user *UserObject, swap bool) {
|
||||||
if counter, loaded := s.userUplink[user.UserName]; loaded {
|
if counter, loaded := s.userUplink[user.UserName]; loaded {
|
||||||
user.UplinkBytes = counter.Load()
|
if swap {
|
||||||
|
user.UplinkBytes = counter.Swap(0)
|
||||||
|
} else {
|
||||||
|
user.UplinkBytes = counter.Load()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if counter, loaded := s.userDownlink[user.UserName]; loaded {
|
if counter, loaded := s.userDownlink[user.UserName]; loaded {
|
||||||
user.DownlinkBytes = counter.Load()
|
if swap {
|
||||||
|
user.DownlinkBytes = counter.Swap(0)
|
||||||
|
} else {
|
||||||
|
user.DownlinkBytes = counter.Load()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if counter, loaded := s.userUplinkPackets[user.UserName]; loaded {
|
if counter, loaded := s.userUplinkPackets[user.UserName]; loaded {
|
||||||
user.UplinkPackets = counter.Load()
|
if swap {
|
||||||
|
user.UplinkPackets = counter.Swap(0)
|
||||||
|
} else {
|
||||||
|
user.UplinkPackets = counter.Load()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if counter, loaded := s.userDownlinkPackets[user.UserName]; loaded {
|
if counter, loaded := s.userDownlinkPackets[user.UserName]; loaded {
|
||||||
user.DownlinkPackets = counter.Load()
|
if swap {
|
||||||
|
user.DownlinkPackets = counter.Swap(0)
|
||||||
|
} else {
|
||||||
|
user.DownlinkPackets = counter.Load()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if counter, loaded := s.userTCPSessions[user.UserName]; loaded {
|
if counter, loaded := s.userTCPSessions[user.UserName]; loaded {
|
||||||
user.TCPSessions = counter.Load()
|
if swap {
|
||||||
|
user.TCPSessions = counter.Swap(0)
|
||||||
|
} else {
|
||||||
|
user.TCPSessions = counter.Load()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if counter, loaded := s.userUDPSessions[user.UserName]; loaded {
|
if counter, loaded := s.userUDPSessions[user.UserName]; loaded {
|
||||||
user.UDPSessions = counter.Load()
|
if swap {
|
||||||
|
user.UDPSessions = counter.Swap(0)
|
||||||
|
} else {
|
||||||
|
user.UDPSessions = counter.Load()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TrafficManager) ReadUsers(users []*UserObject) {
|
func (s *TrafficManager) ReadUsers(users []*UserObject, swap bool) {
|
||||||
s.userAccess.Lock()
|
s.userAccess.Lock()
|
||||||
defer s.userAccess.Unlock()
|
defer s.userAccess.Unlock()
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
s.readUser(user)
|
s.readUser(user, swap)
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TrafficManager) ReadGlobal() (
|
func (s *TrafficManager) ReadGlobal(swap bool) (uplinkBytes int64, downlinkBytes int64, uplinkPackets int64, downlinkPackets int64, tcpSessions int64, udpSessions int64) {
|
||||||
uplinkBytes int64,
|
if swap {
|
||||||
downlinkBytes int64,
|
return s.globalUplink.Swap(0),
|
||||||
uplinkPackets int64,
|
s.globalDownlink.Swap(0),
|
||||||
downlinkPackets int64,
|
s.globalUplinkPackets.Swap(0),
|
||||||
tcpSessions int64,
|
s.globalDownlinkPackets.Swap(0),
|
||||||
udpSessions int64,
|
s.globalTCPSessions.Swap(0),
|
||||||
) {
|
s.globalUDPSessions.Swap(0)
|
||||||
return s.globalUplink.Load(),
|
} else {
|
||||||
s.globalDownlink.Load(),
|
return s.globalUplink.Load(),
|
||||||
s.globalUplinkPackets.Load(),
|
s.globalDownlink.Load(),
|
||||||
s.globalDownlinkPackets.Load(),
|
s.globalUplinkPackets.Load(),
|
||||||
s.globalTCPSessions.Load(),
|
s.globalDownlinkPackets.Load(),
|
||||||
s.globalUDPSessions.Load()
|
s.globalTCPSessions.Load(),
|
||||||
}
|
s.globalUDPSessions.Load()
|
||||||
|
|
||||||
func (s *TrafficManager) Clear() {
|
|
||||||
s.globalUplink.Store(0)
|
|
||||||
s.globalDownlink.Store(0)
|
|
||||||
s.globalUplinkPackets.Store(0)
|
|
||||||
s.globalDownlinkPackets.Store(0)
|
|
||||||
s.globalTCPSessions.Store(0)
|
|
||||||
s.globalUDPSessions.Store(0)
|
|
||||||
s.userAccess.Lock()
|
|
||||||
defer s.userAccess.Unlock()
|
|
||||||
for _, counter := range s.userUplink {
|
|
||||||
counter.Store(0)
|
|
||||||
}
|
|
||||||
for _, counter := range s.userDownlink {
|
|
||||||
counter.Store(0)
|
|
||||||
}
|
|
||||||
for _, counter := range s.userUplinkPackets {
|
|
||||||
counter.Store(0)
|
|
||||||
}
|
|
||||||
for _, counter := range s.userDownlinkPackets {
|
|
||||||
counter.Store(0)
|
|
||||||
}
|
|
||||||
for _, counter := range s.userTCPSessions {
|
|
||||||
counter.Store(0)
|
|
||||||
}
|
|
||||||
for _, counter := range s.userUDPSessions {
|
|
||||||
counter.Store(0)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
@@ -29,7 +30,7 @@ type Client struct {
|
|||||||
serverAddr string
|
serverAddr string
|
||||||
serviceName string
|
serviceName string
|
||||||
dialOptions []grpc.DialOption
|
dialOptions []grpc.DialOption
|
||||||
conn *grpc.ClientConn
|
conn atomic.Pointer[grpc.ClientConn]
|
||||||
connAccess sync.Mutex
|
connAccess sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,13 +75,13 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) connect() (*grpc.ClientConn, error) {
|
func (c *Client) connect() (*grpc.ClientConn, error) {
|
||||||
conn := c.conn
|
conn := c.conn.Load()
|
||||||
if conn != nil && conn.GetState() != connectivity.Shutdown {
|
if conn != nil && conn.GetState() != connectivity.Shutdown {
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
c.connAccess.Lock()
|
c.connAccess.Lock()
|
||||||
defer c.connAccess.Unlock()
|
defer c.connAccess.Unlock()
|
||||||
conn = c.conn
|
conn = c.conn.Load()
|
||||||
if conn != nil && conn.GetState() != connectivity.Shutdown {
|
if conn != nil && conn.GetState() != connectivity.Shutdown {
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
@@ -89,7 +90,7 @@ func (c *Client) connect() (*grpc.ClientConn, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
c.conn = conn
|
c.conn.Store(conn)
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,11 +110,9 @@ func (c *Client) DialContext(ctx context.Context) (net.Conn, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) Close() error {
|
func (c *Client) Close() error {
|
||||||
c.connAccess.Lock()
|
conn := c.conn.Swap(nil)
|
||||||
defer c.connAccess.Unlock()
|
if conn != nil {
|
||||||
if c.conn != nil {
|
conn.Close()
|
||||||
c.conn.Close()
|
|
||||||
c.conn = nil
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user