From d2f1118c2ec3fe754442b96c485e62a5672ec533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Thu, 7 Nov 2024 21:46:53 +0800 Subject: [PATCH] Update dependencies --- cmd/serenity/cmd_check.go | 2 +- cmd/serenity/cmd_export.go | 2 +- cmd/serenity/cmd_format.go | 2 +- cmd/serenity/cmd_run.go | 8 +- cmd/serenity/main.go | 4 + go.mod | 31 +++--- go.sum | 66 +++++------ option/options.go | 16 +-- option/template.go | 13 ++- server/profile.go | 4 +- server/server.go | 3 +- subscription/deduplication.go | 12 +- subscription/parser/clash.go | 15 +-- subscription/parser/link_shadowsocks.go | 2 +- subscription/parser/parser.go | 8 +- subscription/parser/raw.go | 3 +- subscription/parser/sing_box.go | 6 +- subscription/parser/sip008.go | 6 +- subscription/process.go | 25 ++--- subscription/subscription.go | 2 +- template/filter/filter_1100.go | 36 +++--- template/filter/filter_190.go | 9 +- template/filter/filter_null_references.go | 23 ++-- template/manager.go | 8 +- template/render_dns.go | 129 ++++++++++++++++----- template/render_experimental.go | 6 +- template/render_inbounds.go | 59 +++++----- template/render_outbounds.go | 78 +++++++------ template/render_route.go | 130 ++++++++++++++++------ template/template.go | 5 +- 30 files changed, 435 insertions(+), 278 deletions(-) diff --git a/cmd/serenity/cmd_check.go b/cmd/serenity/cmd_check.go index 6cbe72a..3c4cd50 100644 --- a/cmd/serenity/cmd_check.go +++ b/cmd/serenity/cmd_check.go @@ -30,7 +30,7 @@ func check() error { if err != nil { return err } - ctx, cancel := context.WithCancel(context.Background()) + ctx, cancel := context.WithCancel(globalCtx) instance, err := server.New(ctx, options) if err == nil { instance.Close() diff --git a/cmd/serenity/cmd_export.go b/cmd/serenity/cmd_export.go index 844c590..e456cf0 100644 --- a/cmd/serenity/cmd_export.go +++ b/cmd/serenity/cmd_export.go @@ -71,7 +71,7 @@ func export(profileName string) error { } options.Log.DisableColor = true } - ctx, cancel := context.WithCancel(context.Background()) + ctx, cancel := context.WithCancel(globalCtx) instance, err := server.New(ctx, options) if err != nil { cancel() diff --git a/cmd/serenity/cmd_format.go b/cmd/serenity/cmd_format.go index fc47c5a..ab59c9a 100644 --- a/cmd/serenity/cmd_format.go +++ b/cmd/serenity/cmd_format.go @@ -38,7 +38,7 @@ func format() error { return err } for _, optionsEntry := range optionsList { - optionsEntry.options, err = badjson.Omitempty(optionsEntry.options) + optionsEntry.options, err = badjson.Omitempty(globalCtx, optionsEntry.options) if err != nil { return err } diff --git a/cmd/serenity/cmd_run.go b/cmd/serenity/cmd_run.go index f234ce9..418e13a 100644 --- a/cmd/serenity/cmd_run.go +++ b/cmd/serenity/cmd_run.go @@ -58,7 +58,7 @@ func readConfigAt(path string) (*OptionsEntry, error) { if err != nil { return nil, E.Cause(err, "read config at ", path) } - options, err := json.UnmarshalExtended[option.Options](configContent) + options, err := json.UnmarshalExtendedContext[option.Options](globalCtx, configContent) if err != nil { return nil, E.Cause(err, "decode config at ", path) } @@ -110,13 +110,13 @@ func readConfigAndMerge() (option.Options, error) { } var mergedMessage json.RawMessage for _, options := range optionsList { - mergedMessage, err = badjson.MergeJSON(options.options.RawMessage, mergedMessage, false) + mergedMessage, err = badjson.MergeJSON(globalCtx, options.options.RawMessage, mergedMessage, false) if err != nil { return option.Options{}, E.Cause(err, "merge config at ", options.path) } } var mergedOptions option.Options - err = mergedOptions.UnmarshalJSON(mergedMessage) + err = mergedOptions.UnmarshalJSONContext(globalCtx, mergedMessage) if err != nil { return option.Options{}, E.Cause(err, "unmarshal merged config") } @@ -134,7 +134,7 @@ func create() (*server.Server, context.CancelFunc, error) { } options.Log.DisableColor = true } - ctx, cancel := context.WithCancel(context.Background()) + ctx, cancel := context.WithCancel(globalCtx) instance, err := server.New(ctx, options) if err != nil { cancel() diff --git a/cmd/serenity/main.go b/cmd/serenity/main.go index a39c2cc..16258b9 100644 --- a/cmd/serenity/main.go +++ b/cmd/serenity/main.go @@ -5,6 +5,8 @@ import ( "os" "time" + box "github.com/sagernet/sing-box" + "github.com/sagernet/sing-box/include" _ "github.com/sagernet/sing-box/include" "github.com/sagernet/sing-box/log" @@ -16,6 +18,7 @@ var ( configDirectories []string workingDir string disableColor bool + globalCtx context.Context ) var mainCommand = &cobra.Command{ @@ -53,4 +56,5 @@ func preRun(cmd *cobra.Command, args []string) { if len(configPaths) == 0 && len(configDirectories) == 0 { configPaths = append(configPaths, "config.json") } + globalCtx = box.Context(context.Background(), include.InboundRegistry(), include.OutboundRegistry()) } diff --git a/go.mod b/go.mod index 6495edb..ac3740f 100644 --- a/go.mod +++ b/go.mod @@ -11,9 +11,9 @@ require ( github.com/go-chi/render v1.0.3 github.com/miekg/dns v1.1.62 github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a - github.com/sagernet/sing v0.5.0-beta.2 - github.com/sagernet/sing-box v1.10.0-beta.12 - github.com/sagernet/sing-dns v0.3.0-beta.14 + github.com/sagernet/sing v0.5.1-0.20241107131656-6e1285b5d82f + github.com/sagernet/sing-box v1.10.2-0.20241107134520-fead0e42505f + github.com/sagernet/sing-dns v0.3.1-0.20241105104342-1914f319ddab github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 golang.org/x/mod v0.21.0 @@ -21,7 +21,6 @@ require ( ) require ( - berty.tech/go-libtor v1.0.385 // indirect github.com/Dreamacro/protobytes v0.0.0-20230617041236-6500a9f4f158 // indirect github.com/ajg/form v1.5.1 // indirect github.com/andybalholm/brotli v1.0.6 // indirect @@ -35,12 +34,12 @@ require ( github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gobwas/httphead v0.1.0 // indirect github.com/gobwas/pool v0.2.1 // indirect - github.com/gofrs/uuid/v5 v5.2.0 // indirect - github.com/google/btree v1.1.2 // indirect + github.com/gofrs/uuid/v5 v5.3.0 // indirect + github.com/google/btree v1.1.3 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect github.com/gorilla/websocket v1.5.0 // indirect - github.com/hashicorp/yamux v0.1.1 // indirect + github.com/hashicorp/yamux v0.1.2 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 // indirect github.com/josharian/native v1.1.0 // indirect @@ -52,10 +51,9 @@ require ( github.com/logrusorgru/aurora v2.0.3+incompatible // indirect github.com/mdlayher/netlink v1.7.2 // indirect github.com/mdlayher/socket v0.4.1 // indirect - github.com/metacubex/tfo-go v0.0.0-20240821025650-e9be0afd5e7d // indirect + github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa // indirect github.com/mholt/acmez v1.2.0 // indirect github.com/onsi/ginkgo/v2 v2.9.7 // indirect - github.com/ooni/go-libtor v1.1.8 // indirect github.com/oschwald/geoip2-golang v1.9.0 // indirect github.com/oschwald/maxminddb-golang v1.12.0 // indirect github.com/pierrec/lz4/v4 v4.1.14 // indirect @@ -65,16 +63,17 @@ require ( github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 // indirect github.com/sagernet/cors v1.2.1 // indirect github.com/sagernet/fswatch v0.1.1 // indirect - github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f // indirect + github.com/sagernet/gvisor v0.0.0-20241021032506-a4324256e4a3 // indirect github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect github.com/sagernet/nftables v0.3.0-beta.4 // indirect - github.com/sagernet/quic-go v0.47.0-beta.2 // indirect + github.com/sagernet/quic-go v0.48.1-beta.1 // indirect github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect - github.com/sagernet/sing-mux v0.2.0 // indirect - github.com/sagernet/sing-quic v0.3.0-beta.3 // indirect + github.com/sagernet/sing-mux v0.2.1-0.20241020175909-fe6153f7a9ec // indirect + github.com/sagernet/sing-quic v0.3.0-rc.2 // indirect + github.com/sagernet/sing-shadowsocks v0.2.7 // indirect github.com/sagernet/sing-shadowsocks2 v0.2.0 // indirect github.com/sagernet/sing-shadowtls v0.1.4 // indirect - github.com/sagernet/sing-tun v0.4.0-beta.16 // indirect + github.com/sagernet/sing-tun v0.4.0-rc.5.0.20241107062822-5a91eb99c90f // indirect github.com/sagernet/sing-vmess v0.1.12 // indirect github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect github.com/sagernet/utls v1.6.7 // indirect @@ -97,8 +96,8 @@ require ( golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.26.0 // indirect golang.org/x/text v0.19.0 // indirect - golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.23.0 // indirect + golang.org/x/time v0.7.0 // indirect + golang.org/x/tools v0.24.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect google.golang.org/grpc v1.63.2 // indirect google.golang.org/protobuf v1.33.0 // indirect diff --git a/go.sum b/go.sum index a84ebb1..0bb09ef 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -berty.tech/go-libtor v1.0.385 h1:RWK94C3hZj6Z2GdvePpHJLnWYobFr3bY/OdUJ5aoEXw= -berty.tech/go-libtor v1.0.385/go.mod h1:9swOOQVb+kmvuAlsgWUK/4c52pm69AdbJsxLzk+fJEw= github.com/Dreamacro/clash v1.18.0 h1:tic7ykTOCaT0mxwAkXo6QP3LN3Nps8oZz9atgr6TU8A= github.com/Dreamacro/clash v1.18.0/go.mod h1:r//xe/2pA3Zl+3fjIiI/o6RjIVd+z87drCD58dpRnFg= github.com/Dreamacro/protobytes v0.0.0-20230617041236-6500a9f4f158 h1:JFnwKplz9hj8ubqYjm8HkgZS1Rvz9yW+u/XCNNTxr0k= @@ -13,7 +11,6 @@ github.com/caddyserver/certmagic v0.20.0/go.mod h1:N4sXgpICQUskEWpj7zVzvWD41p3NY github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cretz/bine v0.1.0/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw= github.com/cretz/bine v0.2.0 h1:8GiDRGlTgz+o8H9DSnsl+5MeBK4HsExxgl6WgzOCuZo= github.com/cretz/bine v0.2.0/go.mod h1:WU4o9QR9wWp8AVKtTM1XD5vUHkEqnf2vVSo6dBqbetI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -39,20 +36,20 @@ github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gofrs/uuid/v5 v5.2.0 h1:qw1GMx6/y8vhVsx626ImfKMuS5CvJmhIKKtuyvfajMM= -github.com/gofrs/uuid/v5 v5.2.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= +github.com/gofrs/uuid/v5 v5.3.0 h1:m0mUMr+oVYUdxpMLgSYCZiXe7PuVPnI94+OMeVBNedk= +github.com/gofrs/uuid/v5 v5.3.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= -github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk= github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= -github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= +github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= +github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 h1:9K06NfxkBh25x56yVhWWlKFE8YpicaSfHwoV8SFbueA= @@ -80,8 +77,8 @@ github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/ github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= -github.com/metacubex/tfo-go v0.0.0-20240821025650-e9be0afd5e7d h1:j9LtzkYstLFoNvXW824QQeN7Y26uPL5249kzWKbzO9U= -github.com/metacubex/tfo-go v0.0.0-20240821025650-e9be0afd5e7d/go.mod h1:c7bVFM9f5+VzeZ/6Kg77T/jrg1Xp8QpqlSHvG/aXVts= +github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa h1:9mcjV+RGZVC3reJBNDjjNPyS8PmFG97zq56X7WNaFO4= +github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa/go.mod h1:4tLB5c8U0CxpkFM+AJJB77jEaVDbLH5XQvy42vAGsWw= github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30= github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE= github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ= @@ -92,8 +89,6 @@ github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss= github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0= github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU= github.com/onsi/gomega v1.27.7/go.mod h1:1p8OOlwo2iUUDsHnOrjE5UKYJ+e3W8eQ3qSlRahPmr4= -github.com/ooni/go-libtor v1.1.8 h1:Wo3V3DVTxl5vZdxtQakqYP+DAHx7pPtAFSl1bnAa08w= -github.com/ooni/go-libtor v1.1.8/go.mod h1:q1YyLwRD9GeMyeerVvwc0vJ2YgwDLTp2bdVcrh/JXyI= github.com/oschwald/geoip2-golang v1.9.0 h1:uvD3O6fXAXs+usU+UGExshpdP13GAqp4GBrzN7IgKZc= github.com/oschwald/geoip2-golang v1.9.0/go.mod h1:BHK6TvDyATVQhKNbQBdrj9eAvuwOMi2zSFXizL3K81Y= github.com/oschwald/maxminddb-golang v1.12.0 h1:9FnTOD0YOhP7DGxGsq4glzpGy5+w7pq50AS6wALUMYs= @@ -115,33 +110,35 @@ 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/fswatch v0.1.1 h1:YqID+93B7VRfqIH3PArW/XpJv5H4OLEVWDfProGoRQs= github.com/sagernet/fswatch v0.1.1/go.mod h1:nz85laH0mkQqJfaOrqPpkwtU1znMFNVTpT/5oRsVz/o= -github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f h1:NkhuupzH5ch7b/Y/6ZHJWrnNLoiNnSJaow6DPb8VW2I= -github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f/go.mod h1:KXmw+ouSJNOsuRpg4wgwwCQuunrGz4yoAqQjsLjc6N0= +github.com/sagernet/gvisor v0.0.0-20241021032506-a4324256e4a3 h1:RxEz7LhPNiF/gX/Hg+OXr5lqsM9iVAgmaK1L1vzlDRM= +github.com/sagernet/gvisor v0.0.0-20241021032506-a4324256e4a3/go.mod h1:ehZwnT2UpmOWAHFL48XdBhnd4Qu4hN2O3Ji0us3ZHMw= github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZNjr6sGeT00J8uU7JF4cNUdb44/Duis= github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= github.com/sagernet/nftables v0.3.0-beta.4 h1:kbULlAwAC3jvdGAC1P5Fa3GSxVwQJibNenDW2zaXr8I= github.com/sagernet/nftables v0.3.0-beta.4/go.mod h1:OQXAjvjNGGFxaTgVCSTRIhYB5/llyVDeapVoENYBDS8= -github.com/sagernet/quic-go v0.47.0-beta.2 h1:1tCGWFOSaXIeuQaHrwOMJIYvlupjTcaVInGQw5ArULU= -github.com/sagernet/quic-go v0.47.0-beta.2/go.mod h1:bLVKvElSEMNv7pu7SZHscW02TYigzQ5lQu3Nh4wNh8Q= +github.com/sagernet/quic-go v0.48.1-beta.1 h1:ElPaV5yzlXIKZpqFMAcUGax6vddi3zt4AEpT94Z0vwo= +github.com/sagernet/quic-go v0.48.1-beta.1/go.mod h1:1WgdDIVD1Gybp40JTWketeSfKA/+or9YMLaG5VeTk4k= github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc= github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU= github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo= -github.com/sagernet/sing v0.5.0-beta.2 h1:V12EpwtsgYo5OLGjAiGoJobDJZeUsKv0b5y+yGAM6W0= -github.com/sagernet/sing v0.5.0-beta.2/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= -github.com/sagernet/sing-box v1.10.0-beta.12 h1:L8VmlfhImH3niP69BziOLmkATeiLlSELV63XumVGY74= -github.com/sagernet/sing-box v1.10.0-beta.12/go.mod h1:VkzoxRgxB87Z0F2vR00qjmezphU/GG9TtgaUYrAzdY8= -github.com/sagernet/sing-dns v0.3.0-beta.14 h1:/s+fJzYKsvLaNDt/2rjpsrDcN8wmCO2JbX6OFrl8Nww= -github.com/sagernet/sing-dns v0.3.0-beta.14/go.mod h1:rscgSr5ixOPk8XM9ZMLuMXCyldEQ1nLvdl0nfv+lp00= -github.com/sagernet/sing-mux v0.2.0 h1:4C+vd8HztJCWNYfufvgL49xaOoOHXty2+EAjnzN3IYo= -github.com/sagernet/sing-mux v0.2.0/go.mod h1:khzr9AOPocLa+g53dBplwNDz4gdsyx/YM3swtAhlkHQ= -github.com/sagernet/sing-quic v0.3.0-beta.3 h1:8S98VXZxtSiOqVCFbCNbMEvKDPhOF/VNBYMjVC3xMhw= -github.com/sagernet/sing-quic v0.3.0-beta.3/go.mod h1:rFPUlYnSj1Bx9gFSghjCqrCzfGvpjhkisOiTKpjq5vQ= +github.com/sagernet/sing v0.5.1-0.20241107131656-6e1285b5d82f h1:A6+OeV5P1mok0eEEbLh4PidymZ6VZnTZ2uHwfapXgdU= +github.com/sagernet/sing v0.5.1-0.20241107131656-6e1285b5d82f/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= +github.com/sagernet/sing-box v1.10.2-0.20241107134520-fead0e42505f h1:CkGSNvQvZlzm5VuKmc23DiY2WxxHbp1jYux0fh3xRW4= +github.com/sagernet/sing-box v1.10.2-0.20241107134520-fead0e42505f/go.mod h1:3Ujxk8+gNR1Kve68iZFjzxDHLGrFODdsvnth8oakrwk= +github.com/sagernet/sing-dns v0.3.1-0.20241105104342-1914f319ddab h1:djP4EY/KM5T62xscormLflVi7eDlHv6p7md1FHMSArE= +github.com/sagernet/sing-dns v0.3.1-0.20241105104342-1914f319ddab/go.mod h1:TqLIelI+FAbVEdiTRolhGLOwvhVjY7oT+wezlOJUQ7M= +github.com/sagernet/sing-mux v0.2.1-0.20241020175909-fe6153f7a9ec h1:6Fd/VsEsw9qIjaGi1IBTZSb4b4v5JYtNcoiBtGsQC48= +github.com/sagernet/sing-mux v0.2.1-0.20241020175909-fe6153f7a9ec/go.mod h1:RSwqqHwbtTOX3vs6ms8vMtBGH/0ZNyLm/uwt6TlmR84= +github.com/sagernet/sing-quic v0.3.0-rc.2 h1:7vcC4bdS1GBJzHZhfmJiH0CfzQ4mYLUW51Z2RNHcGwc= +github.com/sagernet/sing-quic v0.3.0-rc.2/go.mod h1:3UOq51WVqzra7eCgod7t4hqnTaOiZzFUci9avMrtOqs= +github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8= +github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE= github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg= github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ= github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k= github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4= -github.com/sagernet/sing-tun v0.4.0-beta.16 h1:05VdL5BZiKLQsDNrpdXMseSO1NwPfl9Y4o76PqAd9sY= -github.com/sagernet/sing-tun v0.4.0-beta.16/go.mod h1:81JwnnYw8X9W9XvmZetSTTiPgIE3SbAbnc+EHKwPJ5U= +github.com/sagernet/sing-tun v0.4.0-rc.5.0.20241107062822-5a91eb99c90f h1:gQwTgN/E4oHe3VlseD3/RhPs866cWcTsPG4dP6a8f8o= +github.com/sagernet/sing-tun v0.4.0-rc.5.0.20241107062822-5a91eb99c90f/go.mod h1:Ehs5mZ3T8tTgV3H1Tx4Va5ixvyKjTAUPJ3G11dq7B/g= github.com/sagernet/sing-vmess v0.1.12 h1:2gFD8JJb+eTFMoa8FIVMnknEi+vCSfaiTXTfEYAYAPg= github.com/sagernet/sing-vmess v0.1.12/go.mod h1:luTSsfyBGAc9VhtCqwjR+dt1QgqBhuYBCONB/POhF8I= github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ= @@ -161,7 +158,6 @@ github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3k github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= @@ -191,7 +187,6 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= 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= -golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= @@ -205,7 +200,6 @@ golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -225,11 +219,11 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= +golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= -golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= diff --git a/option/options.go b/option/options.go index ae0ca8e..a674910 100644 --- a/option/options.go +++ b/option/options.go @@ -1,11 +1,13 @@ package option import ( + "context" "time" "github.com/sagernet/sing-box/option" "github.com/sagernet/sing/common/json" "github.com/sagernet/sing/common/json/badjson" + "github.com/sagernet/sing/common/json/badoption" ) type _Options struct { @@ -15,17 +17,17 @@ type _Options struct { TLS *option.InboundTLSOptions `json:"tls,omitempty"` CacheFile string `json:"cache_file,omitempty"` - Outbounds []option.Listable[option.Outbound] `json:"outbounds,omitempty"` - Subscriptions []Subscription `json:"subscriptions,omitempty"` - Templates []Template `json:"templates,omitempty"` - Profiles []Profile `json:"profiles,omitempty"` - Users []User `json:"users,omitempty"` + Outbounds []badoption.Listable[option.Outbound] `json:"outbounds,omitempty"` + Subscriptions []Subscription `json:"subscriptions,omitempty"` + Templates []Template `json:"templates,omitempty"` + Profiles []Profile `json:"profiles,omitempty"` + Users []User `json:"users,omitempty"` } type Options _Options -func (o *Options) UnmarshalJSON(content []byte) error { - err := json.UnmarshalDisallowUnknownFields(content, (*_Options)(o)) +func (o *Options) UnmarshalJSONContext(ctx context.Context, content []byte) error { + err := json.UnmarshalContextDisallowUnknownFields(ctx, content, (*_Options)(o)) if err != nil { return err } diff --git a/option/template.go b/option/template.go index 14e6e12..210db6f 100644 --- a/option/template.go +++ b/option/template.go @@ -1,11 +1,14 @@ package option import ( + "context" + C "github.com/sagernet/serenity/constant" "github.com/sagernet/sing-box/option" "github.com/sagernet/sing-dns" E "github.com/sagernet/sing/common/exceptions" "github.com/sagernet/sing/common/json" + "github.com/sagernet/sing/common/json/badjson" ) type _Template struct { @@ -81,8 +84,8 @@ func (t *Template) MarshalJSON() ([]byte, error) { return json.Marshal((*_Template)(t)) } -func (t *Template) UnmarshalJSON(content []byte) error { - err := json.UnmarshalDisallowUnknownFields(content, (*_Template)(t)) +func (t *Template) UnmarshalJSONContext(ctx context.Context, content []byte) error { + err := json.UnmarshalContextDisallowUnknownFields(ctx, content, (*_Template)(t)) if err != nil { return err } @@ -100,7 +103,7 @@ type RuleSet _RuleSet func (r *RuleSet) MarshalJSON() ([]byte, error) { if r.Type == C.RuleSetTypeGitHub { - return option.MarshallObjects((*_RuleSet)(r), r.GitHubOptions) + return badjson.MarshallObjects((*_RuleSet)(r), r.GitHubOptions) } else { return json.Marshal(r.DefaultOptions) } @@ -112,9 +115,9 @@ func (r *RuleSet) UnmarshalJSON(content []byte) error { return err } if r.Type == C.RuleSetTypeGitHub { - return option.UnmarshallExcluded(content, (*_RuleSet)(r), &r.GitHubOptions) + return badjson.UnmarshallExcluded(content, (*_RuleSet)(r), &r.GitHubOptions) } else { - return option.UnmarshallExcluded(content, (*_RuleSet)(r), &r.DefaultOptions) + return badjson.UnmarshallExcluded(content, (*_RuleSet)(r), &r.DefaultOptions) } } diff --git a/server/profile.go b/server/profile.go index af2cc6e..05c277a 100644 --- a/server/profile.go +++ b/server/profile.go @@ -141,11 +141,11 @@ func (p *Profile) Render(metadata metadata.Metadata) (*boxOption.Options, error) subscriptions := common.Filter(p.manager.subscription.Subscriptions(), func(it *subscription.Subscription) bool { return common.Contains(p.Subscription, it.Name) }) - options, err := selectedTemplate.Render(metadata, p.Name, outbounds, subscriptions) + options, err := selectedTemplate.Render(p.manager.ctx, metadata, p.Name, outbounds, subscriptions) if err != nil { return nil, err } - options, err = badjson.Omitempty(options) + options, err = badjson.Omitempty(p.manager.ctx, options) if err != nil { return nil, E.Cause(err, "omitempty") } diff --git a/server/server.go b/server/server.go index 105bde2..25af1b2 100644 --- a/server/server.go +++ b/server/server.go @@ -18,6 +18,7 @@ import ( "github.com/sagernet/sing/common" E "github.com/sagernet/sing/common/exceptions" F "github.com/sagernet/sing/common/format" + "github.com/sagernet/sing/common/json/badoption" "github.com/sagernet/sing/service" "github.com/go-chi/chi/v5" @@ -99,7 +100,7 @@ func New(ctx context.Context, options option.Options) (*Server, error) { logFactory.NewLogger("profile"), subscriptionManager, templateManager, - common.Map(options.Outbounds, func(it boxOption.Listable[boxOption.Outbound]) []boxOption.Outbound { + common.Map(options.Outbounds, func(it badoption.Listable[boxOption.Outbound]) []boxOption.Outbound { return it }), options.Profiles, diff --git a/subscription/deduplication.go b/subscription/deduplication.go index 29beea0..04b331c 100644 --- a/subscription/deduplication.go +++ b/subscription/deduplication.go @@ -7,7 +7,7 @@ import ( "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" - "github.com/sagernet/sing-dns" + dns "github.com/sagernet/sing-dns" "github.com/sagernet/sing/common" N "github.com/sagernet/sing/common/network" "github.com/sagernet/sing/common/task" @@ -70,11 +70,7 @@ type resolveContext struct { } func resolveDestination(ctx *resolveContext, server option.Outbound) netip.AddrPort { - rawOptions, err := server.RawOptions() - if err != nil { - return netip.AddrPort{} - } - serverOptionsWrapper, loaded := rawOptions.(option.ServerOptionsWrapper) + serverOptionsWrapper, loaded := server.Options.(option.ServerOptionsWrapper) if !loaded { return netip.AddrPort{} } @@ -83,7 +79,9 @@ func resolveDestination(ctx *resolveContext, server option.Outbound) netip.AddrP return serverOptions.AddrPort() } if serverOptions.IsFqdn() { - addresses, lookupErr := ctx.dnsClient.Lookup(ctx.ctx, ctx.dnsTransport, serverOptions.Fqdn, dns.DomainStrategyPreferIPv4) + addresses, lookupErr := ctx.dnsClient.Lookup(ctx.ctx, ctx.dnsTransport, serverOptions.Fqdn, dns.QueryOptions{ + Strategy: dns.DomainStrategyPreferIPv4, + }) if lookupErr == nil && len(addresses) > 0 { return netip.AddrPortFrom(addresses[0], serverOptions.Port) } diff --git a/subscription/parser/clash.go b/subscription/parser/clash.go index f6fd967..41def33 100644 --- a/subscription/parser/clash.go +++ b/subscription/parser/clash.go @@ -1,6 +1,7 @@ package parser import ( + "context" "strings" C "github.com/sagernet/sing-box/constant" @@ -16,7 +17,7 @@ import ( "github.com/Dreamacro/clash/constant" ) -func ParseClashSubscription(content string) ([]option.Outbound, error) { +func ParseClashSubscription(_ context.Context, content string) ([]option.Outbound, error) { config, err := config.UnmarshalRawConfig([]byte(content)) if err != nil { return nil, E.Cause(err, "parse clash config") @@ -38,7 +39,7 @@ func ParseClashSubscription(content string) ([]option.Outbound, error) { return nil, err } outbound.Type = C.TypeShadowsocks - outbound.ShadowsocksOptions = option.ShadowsocksOutboundOptions{ + outbound.Options = &option.ShadowsocksOutboundOptions{ ServerOptions: option.ServerOptions{ Server: ssOption.Server, ServerPort: uint16(ssOption.Port), @@ -56,7 +57,7 @@ func ParseClashSubscription(content string) ([]option.Outbound, error) { return nil, err } outbound.Type = C.TypeShadowsocksR - outbound.ShadowsocksROptions = option.ShadowsocksROutboundOptions{ + outbound.Options = &option.ShadowsocksROutboundOptions{ ServerOptions: option.ServerOptions{ Server: ssrOption.Server, ServerPort: uint16(ssrOption.Port), @@ -76,7 +77,7 @@ func ParseClashSubscription(content string) ([]option.Outbound, error) { return nil, err } outbound.Type = C.TypeTrojan - outbound.TrojanOptions = option.TrojanOutboundOptions{ + outbound.Options = &option.TrojanOutboundOptions{ ServerOptions: option.ServerOptions{ Server: trojanOption.Server, ServerPort: uint16(trojanOption.Port), @@ -100,7 +101,7 @@ func ParseClashSubscription(content string) ([]option.Outbound, error) { return nil, err } outbound.Type = C.TypeVMess - outbound.VMessOptions = option.VMessOutboundOptions{ + outbound.Options = &option.VMessOutboundOptions{ ServerOptions: option.ServerOptions{ Server: vmessOption.Server, ServerPort: uint16(vmessOption.Port), @@ -131,7 +132,7 @@ func ParseClashSubscription(content string) ([]option.Outbound, error) { } outbound.Type = C.TypeSOCKS - outbound.SocksOptions = option.SocksOutboundOptions{ + outbound.Options = &option.SOCKSOutboundOptions{ ServerOptions: option.ServerOptions{ Server: socks5Option.Server, ServerPort: uint16(socks5Option.Port), @@ -152,7 +153,7 @@ func ParseClashSubscription(content string) ([]option.Outbound, error) { } outbound.Type = C.TypeHTTP - outbound.HTTPOptions = option.HTTPOutboundOptions{ + outbound.Options = &option.HTTPOutboundOptions{ ServerOptions: option.ServerOptions{ Server: httpOption.Server, ServerPort: uint16(httpOption.Port), diff --git a/subscription/parser/link_shadowsocks.go b/subscription/parser/link_shadowsocks.go index abd70c8..caa38f1 100644 --- a/subscription/parser/link_shadowsocks.go +++ b/subscription/parser/link_shadowsocks.go @@ -43,7 +43,7 @@ func ParseShadowsocksLink(link string) (option.Outbound, error) { var outbound option.Outbound outbound.Type = C.TypeShadowsocks outbound.Tag = linkURL.Fragment - outbound.ShadowsocksOptions = options + outbound.Options = &options return outbound, nil } diff --git a/subscription/parser/parser.go b/subscription/parser/parser.go index d8fbb63..934e7f0 100644 --- a/subscription/parser/parser.go +++ b/subscription/parser/parser.go @@ -1,21 +1,23 @@ package parser import ( + "context" + "github.com/sagernet/sing-box/option" E "github.com/sagernet/sing/common/exceptions" ) -var subscriptionParsers = []func(string) ([]option.Outbound, error){ +var subscriptionParsers = []func(ctx context.Context, content string) ([]option.Outbound, error){ ParseBoxSubscription, ParseClashSubscription, ParseSIP008Subscription, ParseRawSubscription, } -func ParseSubscription(content string) ([]option.Outbound, error) { +func ParseSubscription(ctx context.Context, content string) ([]option.Outbound, error) { var pErr error for _, parser := range subscriptionParsers { - servers, err := parser(content) + servers, err := parser(ctx, content) if len(servers) > 0 { return servers, nil } diff --git a/subscription/parser/raw.go b/subscription/parser/raw.go index d352cf4..aa7a75c 100644 --- a/subscription/parser/raw.go +++ b/subscription/parser/raw.go @@ -1,6 +1,7 @@ package parser import ( + "context" "encoding/base64" "strings" @@ -8,7 +9,7 @@ import ( E "github.com/sagernet/sing/common/exceptions" ) -func ParseRawSubscription(content string) ([]option.Outbound, error) { +func ParseRawSubscription(_ context.Context, content string) ([]option.Outbound, error) { if base64Content, err := decodeBase64URLSafe(content); err == nil { servers, _ := parseRawSubscription(base64Content) if len(servers) > 0 { diff --git a/subscription/parser/sing_box.go b/subscription/parser/sing_box.go index b95f171..b442189 100644 --- a/subscription/parser/sing_box.go +++ b/subscription/parser/sing_box.go @@ -1,6 +1,8 @@ package parser import ( + "context" + C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/option" "github.com/sagernet/sing/common" @@ -8,8 +10,8 @@ import ( "github.com/sagernet/sing/common/json" ) -func ParseBoxSubscription(content string) ([]option.Outbound, error) { - options, err := json.UnmarshalExtended[option.Options]([]byte(content)) +func ParseBoxSubscription(ctx context.Context, content string) ([]option.Outbound, error) { + options, err := json.UnmarshalExtendedContext[option.Options](ctx, []byte(content)) if err != nil { return nil, err } diff --git a/subscription/parser/sip008.go b/subscription/parser/sip008.go index 60a6a30..9d07cd1 100644 --- a/subscription/parser/sip008.go +++ b/subscription/parser/sip008.go @@ -1,6 +1,8 @@ package parser import ( + "context" + C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/option" E "github.com/sagernet/sing/common/exceptions" @@ -23,7 +25,7 @@ type ShadowsocksServerDocument struct { PluginOpts string `json:"plugin_opts"` } -func ParseSIP008Subscription(content string) ([]option.Outbound, error) { +func ParseSIP008Subscription(_ context.Context, content string) ([]option.Outbound, error) { var document ShadowsocksDocument err := json.Unmarshal([]byte(content), &document) if err != nil { @@ -35,7 +37,7 @@ func ParseSIP008Subscription(content string) ([]option.Outbound, error) { servers = append(servers, option.Outbound{ Type: C.TypeShadowsocks, Tag: server.Remarks, - ShadowsocksOptions: option.ShadowsocksOutboundOptions{ + Options: &option.ShadowsocksOutboundOptions{ ServerOptions: option.ServerOptions{ Server: server.Server, ServerPort: uint16(server.ServerPort), diff --git a/subscription/process.go b/subscription/process.go index a845832..92aa4eb 100644 --- a/subscription/process.go +++ b/subscription/process.go @@ -5,7 +5,6 @@ import ( "strings" "github.com/sagernet/serenity/option" - C "github.com/sagernet/sing-box/constant" boxOption "github.com/sagernet/sing-box/option" "github.com/sagernet/sing/common" E "github.com/sagernet/sing/common/exceptions" @@ -120,26 +119,22 @@ func (o *ProcessOptions) Process(outbounds []boxOption.Outbound) []boxOption.Out renameResult[originTag] = outbound.Tag } if o.RewriteMultiplex != nil { - switch outbound.Type { - case C.TypeShadowsocks: - outbound.ShadowsocksOptions.Multiplex = o.RewriteMultiplex - case C.TypeTrojan: - outbound.TrojanOptions.Multiplex = o.RewriteMultiplex - case C.TypeVMess: - outbound.VMessOptions.Multiplex = o.RewriteMultiplex - case C.TypeVLESS: - outbound.VLESSOptions.Multiplex = o.RewriteMultiplex + switch outboundOptions := outbound.Options.(type) { + case *boxOption.ShadowsocksOutboundOptions: + outboundOptions.Multiplex = o.RewriteMultiplex + case *boxOption.TrojanOutboundOptions: + outboundOptions.Multiplex = o.RewriteMultiplex + case *boxOption.VMessOutboundOptions: + outboundOptions.Multiplex = o.RewriteMultiplex + case *boxOption.VLESSOutboundOptions: + outboundOptions.Multiplex = o.RewriteMultiplex } } newOutbounds = append(newOutbounds, outbound) } if len(renameResult) > 0 { for i, outbound := range newOutbounds { - rawOptions, err := outbound.RawOptions() - if err != nil { - continue - } - if dialerOptionsWrapper, containsDialerOptions := rawOptions.(boxOption.DialerOptionsWrapper); containsDialerOptions { + if dialerOptionsWrapper, containsDialerOptions := outbound.Options.(boxOption.DialerOptionsWrapper); containsDialerOptions { dialerOptions := dialerOptionsWrapper.TakeDialerOptions() if dialerOptions.Detour == "" { continue diff --git a/subscription/subscription.go b/subscription/subscription.go index 1f0e6a0..319bed0 100644 --- a/subscription/subscription.go +++ b/subscription/subscription.go @@ -187,7 +187,7 @@ func (m *Manager) update(subscription *Subscription) error { response.Body.Close() return err } - rawServers, err := parser.ParseSubscription(string(content)) + rawServers, err := parser.ParseSubscription(m.ctx, string(content)) if err != nil { response.Body.Close() return err diff --git a/template/filter/filter_1100.go b/template/filter/filter_1100.go index 17e571e..b6f9250 100644 --- a/template/filter/filter_1100.go +++ b/template/filter/filter_1100.go @@ -1,6 +1,7 @@ package filter import ( + "context" "net/netip" "github.com/sagernet/serenity/common/metadata" @@ -77,41 +78,42 @@ func filter1100(metadata metadata.Metadata, options *option.Options) error { newInbounds := make([]option.Inbound, 0, len(options.Inbounds)) for _, inbound := range options.Inbounds { if inbound.Type == C.TypeTun { - inbound.TunOptions.AutoRedirect = false - inbound.TunOptions.RouteAddressSet = nil - inbound.TunOptions.RouteExcludeAddressSet = nil + tunOptions := inbound.Options.(*option.TunInboundOptions) + tunOptions.AutoRedirect = false + tunOptions.RouteAddressSet = nil + tunOptions.RouteExcludeAddressSet = nil //nolint:staticcheck //goland:noinspection GoDeprecation - if len(inbound.TunOptions.Address) > 0 { - inbound.TunOptions.Inet4Address = append(inbound.TunOptions.Inet4Address, common.Filter(inbound.TunOptions.Address, func(it netip.Prefix) bool { + if len(tunOptions.Address) > 0 { + tunOptions.Inet4Address = append(tunOptions.Inet4Address, common.Filter(tunOptions.Address, func(it netip.Prefix) bool { return it.Addr().Is4() })...) - inbound.TunOptions.Inet6Address = append(inbound.TunOptions.Inet6Address, common.Filter(inbound.TunOptions.Address, func(it netip.Prefix) bool { + tunOptions.Inet6Address = append(tunOptions.Inet6Address, common.Filter(tunOptions.Address, func(it netip.Prefix) bool { return it.Addr().Is6() })...) - inbound.TunOptions.Address = nil + tunOptions.Address = nil } //nolint:staticcheck //goland:noinspection GoDeprecation - if len(inbound.TunOptions.RouteAddress) > 0 { - inbound.TunOptions.Inet4RouteAddress = append(inbound.TunOptions.Inet4RouteAddress, common.Filter(inbound.TunOptions.RouteAddress, func(it netip.Prefix) bool { + if len(tunOptions.RouteAddress) > 0 { + tunOptions.Inet4RouteAddress = append(tunOptions.Inet4RouteAddress, common.Filter(tunOptions.RouteAddress, func(it netip.Prefix) bool { return it.Addr().Is4() })...) - inbound.TunOptions.Inet6RouteAddress = append(inbound.TunOptions.Inet6RouteAddress, common.Filter(inbound.TunOptions.RouteAddress, func(it netip.Prefix) bool { + tunOptions.Inet6RouteAddress = append(tunOptions.Inet6RouteAddress, common.Filter(tunOptions.RouteAddress, func(it netip.Prefix) bool { return it.Addr().Is6() })...) - inbound.TunOptions.RouteAddress = nil + tunOptions.RouteAddress = nil } //nolint:staticcheck //goland:noinspection GoDeprecation - if len(inbound.TunOptions.RouteExcludeAddress) > 0 { - inbound.TunOptions.Inet4RouteExcludeAddress = append(inbound.TunOptions.Inet4RouteExcludeAddress, common.Filter(inbound.TunOptions.RouteExcludeAddress, func(it netip.Prefix) bool { + if len(tunOptions.RouteExcludeAddress) > 0 { + tunOptions.Inet4RouteExcludeAddress = append(tunOptions.Inet4RouteExcludeAddress, common.Filter(tunOptions.RouteExcludeAddress, func(it netip.Prefix) bool { return it.Addr().Is4() })...) - inbound.TunOptions.Inet6RouteExcludeAddress = append(inbound.TunOptions.Inet6RouteExcludeAddress, common.Filter(inbound.TunOptions.RouteExcludeAddress, func(it netip.Prefix) bool { + tunOptions.Inet6RouteExcludeAddress = append(tunOptions.Inet6RouteExcludeAddress, common.Filter(tunOptions.RouteExcludeAddress, func(it netip.Prefix) bool { return it.Addr().Is6() })...) - inbound.TunOptions.RouteExcludeAddress = nil + tunOptions.RouteExcludeAddress = nil } } newInbounds = append(newInbounds, inbound) @@ -152,7 +154,7 @@ func expandInlineRule(ruleSet option.RuleSet, rule option.Rule) ([]option.Rule, if err != nil { return nil, E.Cause(err, "marshal inline rule ", ruleSet.Tag, "[", i, "]") } - newRule, err = badjson.MergeFromSource(rawRule, rule, false) + newRule, err = badjson.MergeFromSource(context.Background(), rawRule, rule, false) if err != nil { return nil, E.Cause(err, "merge inline rule ", ruleSet.Tag, "[", i, "]") } @@ -192,7 +194,7 @@ func expandInlineDNSRule(ruleSet option.RuleSet, rule option.DNSRule) ([]option. if err != nil { return nil, E.Cause(err, "marshal inline rule ", ruleSet.Tag, "[", i, "]") } - newRule, err = badjson.MergeFromSource(rawRule, rule, false) + newRule, err = badjson.MergeFromSource(context.Background(), rawRule, rule, false) if err != nil { return nil, E.Cause(err, "merge inline rule ", ruleSet.Tag, "[", i, "]") } diff --git a/template/filter/filter_190.go b/template/filter/filter_190.go index e3fb2df..41f2e31 100644 --- a/template/filter/filter_190.go +++ b/template/filter/filter_190.go @@ -3,7 +3,6 @@ package filter import ( "github.com/sagernet/serenity/common/metadata" "github.com/sagernet/serenity/common/semver" - C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/option" "github.com/sagernet/sing/common" ) @@ -24,12 +23,12 @@ func filter190(metadata metadata.Metadata, options *option.Options) error { return nil } for _, inbound := range options.Inbounds { - switch inbound.Type { - case C.TypeTun: - if inbound.TunOptions.Platform == nil || inbound.TunOptions.Platform.HTTPProxy == nil { + switch inboundOptions := inbound.Options.(type) { + case *option.TunInboundOptions: + if inboundOptions.Platform == nil || inboundOptions.Platform.HTTPProxy == nil { continue } - httpProxy := inbound.TunOptions.Platform.HTTPProxy + httpProxy := inboundOptions.Platform.HTTPProxy if len(httpProxy.BypassDomain) > 0 || len(httpProxy.MatchDomain) > 0 { httpProxy.BypassDomain = nil httpProxy.MatchDomain = nil diff --git a/template/filter/filter_null_references.go b/template/filter/filter_null_references.go index a34e2fc..3f88beb 100644 --- a/template/filter/filter_null_references.go +++ b/template/filter/filter_null_references.go @@ -15,27 +15,32 @@ func filterNullGroupReference(metadata M.Metadata, options *option.Options) erro outboundTags := common.Map(options.Outbounds, func(it option.Outbound) string { return it.Tag }) - for i, outbound := range options.Outbounds { - switch outbound.Type { - case C.TypeSelector: - outbound.SelectorOptions.Outbounds = common.Filter(outbound.SelectorOptions.Outbounds, func(outbound string) bool { + for _, outbound := range options.Outbounds { + switch outboundOptions := outbound.Options.(type) { + case *option.SelectorOutboundOptions: + outboundOptions.Outbounds = common.Filter(outboundOptions.Outbounds, func(outbound string) bool { return common.Contains(outboundTags, outbound) }) - case C.TypeURLTest: - outbound.URLTestOptions.Outbounds = common.Filter(outbound.URLTestOptions.Outbounds, func(outbound string) bool { + case *option.URLTestOutboundOptions: + outboundOptions.Outbounds = common.Filter(outboundOptions.Outbounds, func(outbound string) bool { return common.Contains(outboundTags, outbound) }) default: continue } - options.Outbounds[i] = outbound } options.Route.Rules = common.Filter(options.Route.Rules, func(it option.Rule) bool { switch it.Type { case C.RuleTypeDefault: - return common.Contains(outboundTags, it.DefaultOptions.Outbound) + if it.DefaultOptions.Action != C.RuleActionTypeRoute { + return true + } + return common.Contains(outboundTags, it.DefaultOptions.RouteOptions.Outbound) case C.RuleTypeLogical: - return common.Contains(outboundTags, it.LogicalOptions.Outbound) + if it.LogicalOptions.Action != C.RuleActionTypeRoute { + return true + } + return common.Contains(outboundTags, it.LogicalOptions.RouteOptions.Outbound) default: panic("no") } diff --git a/template/manager.go b/template/manager.go index def403b..f2f5c81 100644 --- a/template/manager.go +++ b/template/manager.go @@ -18,7 +18,7 @@ type Manager struct { templates []*Template } -func extendTemplate(rawTemplates []option.Template, root, current option.Template) (option.Template, error) { +func extendTemplate(ctx context.Context, rawTemplates []option.Template, root, current option.Template) (option.Template, error) { if current.Extend == "" { return current, nil } else if root.Name == current.Extend { @@ -35,13 +35,13 @@ func extendTemplate(rawTemplates []option.Template, root, current option.Templat return option.Template{}, E.New("initialize template[", current.Name, "]: extended template not found: ", current.Extend) } if next.Extend != "" { - newNext, err := extendTemplate(rawTemplates, root, next) + newNext, err := extendTemplate(ctx, rawTemplates, root, next) if err != nil { return option.Template{}, E.Cause(err, next.Extend) } next = newNext } - newRawTemplate, err := badjson.MergeJSON(next.RawMessage, current.RawMessage, false) + newRawTemplate, err := badjson.MergeJSON(ctx, next.RawMessage, current.RawMessage, false) if err != nil { return option.Template{}, E.Cause(err, "initialize template[", current.Name, "]: merge extended template: ", current.Extend) } @@ -60,7 +60,7 @@ func NewManager(ctx context.Context, logger logger.Logger, rawTemplates []option return nil, E.New("initialize template[", templateIndex, "]: missing name") } if template.Extend != "" { - newTemplate, err := extendTemplate(rawTemplates, template, template) + newTemplate, err := extendTemplate(ctx, rawTemplates, template, template) if err != nil { return nil, err } diff --git a/template/render_dns.go b/template/render_dns.go index 5411d2b..bb4880a 100644 --- a/template/render_dns.go +++ b/template/render_dns.go @@ -110,8 +110,15 @@ func (t *Template) renderDNS(metadata M.Metadata, options *option.Options) error { Type: C.RuleTypeDefault, DefaultOptions: option.DefaultDNSRule{ - Outbound: []string{"any"}, - Server: DNSLocalTag, + RawDefaultDNSRule: option.RawDefaultDNSRule{ + Outbound: []string{"any"}, + }, + DNSRuleAction: option.DNSRuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.DNSRouteActionOptions{ + Server: DNSLocalTag, + }, + }, }, }, } @@ -132,14 +139,28 @@ func (t *Template) renderDNS(metadata M.Metadata, options *option.Options) error options.DNS.Rules = append(options.DNS.Rules, option.DNSRule{ Type: C.RuleTypeDefault, DefaultOptions: option.DefaultDNSRule{ - ClashMode: clashModeGlobal, - Server: DNSDefaultTag, + RawDefaultDNSRule: option.RawDefaultDNSRule{ + ClashMode: clashModeGlobal, + }, + DNSRuleAction: option.DNSRuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.DNSRouteActionOptions{ + Server: DNSDefaultTag, + }, + }, }, }, option.DNSRule{ Type: C.RuleTypeDefault, DefaultOptions: option.DefaultDNSRule{ - ClashMode: clashModeDirect, - Server: DNSLocalTag, + RawDefaultDNSRule: option.RawDefaultDNSRule{ + ClashMode: clashModeDirect, + }, + DNSRuleAction: option.DNSRuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.DNSRouteActionOptions{ + Server: DNSLocalTag, + }, + }, }, }) } @@ -150,16 +171,30 @@ func (t *Template) renderDNS(metadata M.Metadata, options *option.Options) error options.DNS.Rules = append(options.DNS.Rules, option.DNSRule{ Type: C.RuleTypeDefault, DefaultOptions: option.DefaultDNSRule{ - Geosite: []string{"geolocation-cn"}, - Server: DNSLocalTag, + RawDefaultDNSRule: option.RawDefaultDNSRule{ + Geosite: []string{"geolocation-cn"}, + }, + DNSRuleAction: option.DNSRuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.DNSRouteActionOptions{ + Server: DNSLocalTag, + }, + }, }, }) } else { options.DNS.Rules = append(options.DNS.Rules, option.DNSRule{ Type: C.RuleTypeDefault, DefaultOptions: option.DefaultDNSRule{ - RuleSet: []string{"geosite-geolocation-cn"}, - Server: DNSLocalTag, + RawDefaultDNSRule: option.RawDefaultDNSRule{ + RuleSet: []string{"geosite-geolocation-cn"}, + }, + DNSRuleAction: option.DNSRuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.DNSRouteActionOptions{ + Server: DNSLocalTag, + }, + }, }, }) } @@ -167,29 +202,58 @@ func (t *Template) renderDNS(metadata M.Metadata, options *option.Options) error options.DNS.Rules = append(options.DNS.Rules, option.DNSRule{ Type: C.RuleTypeDefault, DefaultOptions: option.DefaultDNSRule{ - ClashMode: clashModeRule, - Server: DNSDefaultTag, + RawDefaultDNSRule: option.RawDefaultDNSRule{ + ClashMode: clashModeRule, + }, + DNSRuleAction: option.DNSRuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.DNSRouteActionOptions{ + Server: DNSDefaultTag, + }, + }, }, }, option.DNSRule{ Type: C.RuleTypeLogical, LogicalOptions: option.LogicalDNSRule{ - Mode: C.LogicalTypeAnd, - Rules: []option.DNSRule{ - { - Type: C.RuleTypeDefault, - DefaultOptions: option.DefaultDNSRule{ - RuleSet: []string{"geosite-geolocation-!cn"}, - Invert: true, + RawLogicalDNSRule: option.RawLogicalDNSRule{ + Mode: C.LogicalTypeAnd, + Rules: []option.DNSRule{ + { + Type: C.RuleTypeDefault, + DefaultOptions: option.DefaultDNSRule{ + RawDefaultDNSRule: option.RawDefaultDNSRule{ + RuleSet: []string{"geosite-geolocation-!cn"}, + }, + DNSRuleAction: option.DNSRuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.DNSRouteActionOptions{ + Server: DNSDefaultTag, + }, + }, + }, }, - }, - { - Type: C.RuleTypeDefault, - DefaultOptions: option.DefaultDNSRule{ - RuleSet: []string{"geoip-cn"}, + { + Type: C.RuleTypeDefault, + DefaultOptions: option.DefaultDNSRule{ + RawDefaultDNSRule: option.RawDefaultDNSRule{ + RuleSet: []string{"geoip-cn"}, + }, + DNSRuleAction: option.DNSRuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.DNSRouteActionOptions{ + Server: DNSLocalTag, + }, + }, + }, }, }, }, - Server: DNSLocalTag, + DNSRuleAction: option.DNSRuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.DNSRouteActionOptions{ + Server: DNSLocalTag, + }, + }, }, }) } @@ -201,11 +265,18 @@ func (t *Template) renderDNS(metadata M.Metadata, options *option.Options) error options.DNS.Rules = append(options.DNS.Rules, option.DNSRule{ Type: C.RuleTypeDefault, DefaultOptions: option.DefaultDNSRule{ - QueryType: []option.DNSQueryType{ - option.DNSQueryType(mDNS.TypeA), - option.DNSQueryType(mDNS.TypeAAAA), + RawDefaultDNSRule: option.RawDefaultDNSRule{ + QueryType: []option.DNSQueryType{ + option.DNSQueryType(mDNS.TypeA), + option.DNSQueryType(mDNS.TypeAAAA), + }, + }, + DNSRuleAction: option.DNSRuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.DNSRouteActionOptions{ + Server: DNSFakeIPTag, + }, }, - Server: DNSFakeIPTag, }, }) } diff --git a/template/render_experimental.go b/template/render_experimental.go index 75f0663..a1488d9 100644 --- a/template/render_experimental.go +++ b/template/render_experimental.go @@ -1,6 +1,8 @@ package template import ( + "context" + M "github.com/sagernet/serenity/common/metadata" "github.com/sagernet/serenity/common/semver" "github.com/sagernet/sing-box/option" @@ -8,7 +10,7 @@ import ( "github.com/sagernet/sing/common/json/badjson" ) -func (t *Template) renderExperimental(metadata M.Metadata, options *option.Options, profileName string) error { +func (t *Template) renderExperimental(ctx context.Context, metadata M.Metadata, options *option.Options, profileName string) error { if t.DisableCacheFile && t.DisableClashMode && t.CustomClashAPI == nil { return nil } @@ -37,7 +39,7 @@ func (t *Template) renderExperimental(metadata M.Metadata, options *option.Optio } if t.CustomClashAPI != nil { - newClashOptions, err := badjson.MergeFromDestination(options.Experimental.ClashAPI, t.CustomClashAPI.Message, true) + newClashOptions, err := badjson.MergeFromDestination(ctx, options.Experimental.ClashAPI, t.CustomClashAPI.Message, true) if err != nil { return err } diff --git a/template/render_inbounds.go b/template/render_inbounds.go index 136fab7..9de41ad 100644 --- a/template/render_inbounds.go +++ b/template/render_inbounds.go @@ -1,6 +1,7 @@ package template import ( + "context" "net/netip" M "github.com/sagernet/serenity/common/metadata" @@ -36,27 +37,28 @@ func (t *Template) renderInbounds(metadata M.Metadata, options *option.Options) if !t.DisableIPv6() { address = append(address, netip.MustParsePrefix("fdfe:dcba:9876::1/126")) } - tunInbound := option.Inbound{ - Type: C.TypeTun, - TunOptions: option.TunInboundOptions{ - AutoRoute: true, - Address: address, - InboundOptions: option.InboundOptions{ - SniffEnabled: needSniff, - }, + tunOptions := &option.TunInboundOptions{ + AutoRoute: true, + Address: address, + InboundOptions: option.InboundOptions{ + SniffEnabled: needSniff, }, } + tunInbound := option.Inbound{ + Type: C.TypeTun, + Options: tunOptions, + } if autoRedirect { - tunInbound.TunOptions.AutoRedirect = true + tunOptions.AutoRedirect = true if !t.DisableTrafficBypass && metadata.Platform == "" { - tunInbound.TunOptions.RouteExcludeAddressSet = []string{"geoip-cn"} + tunOptions.RouteExcludeAddressSet = []string{"geoip-cn"} } } if t.EnableFakeIP { - tunInbound.TunOptions.InboundOptions.DomainStrategy = domainStrategy + tunOptions.DomainStrategy = domainStrategy } if metadata.Platform == M.PlatformUnknown { - tunInbound.TunOptions.StrictRoute = true + tunOptions.StrictRoute = true } if !t.DisableSystemProxy && metadata.Platform != M.PlatformUnknown { var httpPort uint16 @@ -66,7 +68,7 @@ func (t *Template) renderInbounds(metadata M.Metadata, options *option.Options) if httpPort == 0 { httpPort = DefaultMixedPort } - tunInbound.TunOptions.Platform = &option.TunPlatformOptions{ + tunOptions.Platform = &option.TunPlatformOptions{ HTTPProxy: &option.HTTPProxyOptions{ Enabled: true, ServerOptions: option.ServerOptions{ @@ -77,35 +79,36 @@ func (t *Template) renderInbounds(metadata M.Metadata, options *option.Options) } } if t.CustomTUN != nil { - newTUNOptions, err := badjson.MergeFromDestination(tunInbound.TunOptions, t.CustomTUN.Message, true) + newTUNOptions, err := badjson.MergeFromDestination(context.Background(), tunOptions, t.CustomTUN.Message, true) if err != nil { return E.Cause(err, "merge custom tun options") } - tunInbound.TunOptions = newTUNOptions + tunInbound.Options = newTUNOptions } options.Inbounds = append(options.Inbounds, tunInbound) } if disableTun || !t.DisableSystemProxy { - mixedInbound := option.Inbound{ - Type: C.TypeMixed, - MixedOptions: option.HTTPMixedInboundOptions{ - ListenOptions: option.ListenOptions{ - Listen: option.NewListenAddress(netip.AddrFrom4([4]byte{127, 0, 0, 1})), - ListenPort: DefaultMixedPort, - InboundOptions: option.InboundOptions{ - SniffEnabled: needSniff, - DomainStrategy: domainStrategy, - }, + mixedOptions := &option.HTTPMixedInboundOptions{ + ListenOptions: option.ListenOptions{ + Listen: option.NewListenAddress(netip.AddrFrom4([4]byte{127, 0, 0, 1})), + ListenPort: DefaultMixedPort, + InboundOptions: option.InboundOptions{ + SniffEnabled: needSniff, + DomainStrategy: domainStrategy, }, - SetSystemProxy: metadata.Platform == M.PlatformUnknown && disableTun && !t.DisableSystemProxy, }, + SetSystemProxy: metadata.Platform == M.PlatformUnknown && disableTun && !t.DisableSystemProxy, + } + mixedInbound := option.Inbound{ + Type: C.TypeMixed, + Options: mixedOptions, } if t.CustomMixed != nil { - newMixedOptions, err := badjson.MergeFromDestination(mixedInbound.MixedOptions, t.CustomMixed.Message, true) + newMixedOptions, err := badjson.MergeFromDestination(context.Background(), mixedOptions, t.CustomMixed.Message, true) if err != nil { return E.Cause(err, "merge custom mixed options") } - mixedInbound.MixedOptions = newMixedOptions + mixedInbound.Options = newMixedOptions } options.Inbounds = append(options.Inbounds, mixedInbound) } diff --git a/template/render_outbounds.go b/template/render_outbounds.go index c1c6014..955a6d8 100644 --- a/template/render_outbounds.go +++ b/template/render_outbounds.go @@ -31,22 +31,24 @@ func (t *Template) renderOutbounds(metadata M.Metadata, options *boxOption.Optio } options.Outbounds = []boxOption.Outbound{ { - Tag: directTag, - Type: C.TypeDirect, - DirectOptions: common.PtrValueOrDefault(t.CustomDirect), + Tag: directTag, + Type: C.TypeDirect, + Options: common.Ptr(common.PtrValueOrDefault(t.CustomDirect)), }, { - Tag: blockTag, - Type: C.TypeBlock, + Tag: blockTag, + Type: C.TypeBlock, + Options: &boxOption.StubOptions{}, }, { - Tag: DNSTag, - Type: C.TypeDNS, + Tag: DNSTag, + Type: C.TypeDNS, + Options: &boxOption.StubOptions{}, }, { - Tag: defaultTag, - Type: C.TypeSelector, - SelectorOptions: common.PtrValueOrDefault(t.CustomSelector), + Tag: defaultTag, + Type: C.TypeSelector, + Options: common.Ptr(common.PtrValueOrDefault(t.CustomSelector)), }, } urlTestTag := t.URLTestTag @@ -80,12 +82,13 @@ func (t *Template) renderOutbounds(metadata M.Metadata, options *boxOption.Optio return it.Tag }) if it.GenerateSelector { + selectorOptions := common.PtrValueOrDefault(it.CustomSelector) selectorOutbound := boxOption.Outbound{ - Type: C.TypeSelector, - Tag: it.Name, - SelectorOptions: common.PtrValueOrDefault(it.CustomSelector), + Type: C.TypeSelector, + Tag: it.Name, + Options: &selectorOptions, } - selectorOutbound.SelectorOptions.Outbounds = append(selectorOutbound.SelectorOptions.Outbounds, joinOutbounds...) + selectorOptions.Outbounds = append(selectorOptions.Outbounds, joinOutbounds...) allGroups = append(allGroups, selectorOutbound) groupTags = append(groupTags, selectorOutbound.Tag) } @@ -98,12 +101,13 @@ func (t *Template) renderOutbounds(metadata M.Metadata, options *boxOption.Optio } else { urltestTag = it.Name + " - URLTest" } + urltestOptions := common.PtrValueOrDefault(t.CustomURLTest) urltestOutbound := boxOption.Outbound{ - Type: C.TypeURLTest, - Tag: urltestTag, - URLTestOptions: common.PtrValueOrDefault(t.CustomURLTest), + Type: C.TypeURLTest, + Tag: urltestTag, + Options: &urltestOptions, } - urltestOutbound.URLTestOptions.Outbounds = append(urltestOutbound.URLTestOptions.Outbounds, joinOutbounds...) + urltestOptions.Outbounds = append(urltestOptions.Outbounds, joinOutbounds...) allGroups = append(allGroups, urltestOutbound) groupTags = append(groupTags, urltestOutbound.Tag) } @@ -144,16 +148,18 @@ func (t *Template) renderOutbounds(metadata M.Metadata, options *boxOption.Optio continue } groupOutbound := boxOption.Outbound{ - Tag: extraGroup.Tag, - Type: extraGroup.Type, - SelectorOptions: common.PtrValueOrDefault(extraGroup.CustomSelector), - URLTestOptions: common.PtrValueOrDefault(extraGroup.CustomURLTest), + Tag: extraGroup.Tag, + Type: extraGroup.Type, } switch extraGroup.Type { case C.TypeSelector: - groupOutbound.SelectorOptions.Outbounds = append(groupOutbound.SelectorOptions.Outbounds, extraTags...) + selectorOptions := common.PtrValueOrDefault(extraGroup.CustomSelector) + groupOutbound.Options = &selectorOptions + selectorOptions.Outbounds = append(selectorOptions.Outbounds, extraTags...) case C.TypeURLTest: - groupOutbound.URLTestOptions.Outbounds = append(groupOutbound.URLTestOptions.Outbounds, extraTags...) + urltestOptions := common.PtrValueOrDefault(extraGroup.CustomURLTest) + groupOutbound.Options = &urltestOptions + urltestOptions.Outbounds = append(urltestOptions.Outbounds, extraTags...) } if extraGroup.Target == option.ExtraGroupTargetDefault { defaultGroups = append(defaultGroups, groupOutbound) @@ -191,16 +197,18 @@ func (t *Template) renderOutbounds(metadata M.Metadata, options *boxOption.Optio tagPerSubscription = buffer.String() } groupOutboundPerSubscription := boxOption.Outbound{ - Tag: tagPerSubscription, - Type: extraGroup.Type, - SelectorOptions: common.PtrValueOrDefault(extraGroup.CustomSelector), - URLTestOptions: common.PtrValueOrDefault(extraGroup.CustomURLTest), + Tag: tagPerSubscription, + Type: extraGroup.Type, } switch extraGroup.Type { case C.TypeSelector: - groupOutboundPerSubscription.SelectorOptions.Outbounds = append(groupOutboundPerSubscription.SelectorOptions.Outbounds, subscriptionTags...) + selectorOptions := common.PtrValueOrDefault(extraGroup.CustomSelector) + groupOutboundPerSubscription.Options = &selectorOptions + selectorOptions.Outbounds = append(selectorOptions.Outbounds, subscriptionTags...) case C.TypeURLTest: - groupOutboundPerSubscription.URLTestOptions.Outbounds = append(groupOutboundPerSubscription.URLTestOptions.Outbounds, subscriptionTags...) + urltestOptions := common.PtrValueOrDefault(extraGroup.CustomURLTest) + groupOutboundPerSubscription.Options = &urltestOptions + urltestOptions.Outbounds = append(urltestOptions.Outbounds, subscriptionTags...) } subscriptionGroups[it.Name] = append(subscriptionGroups[it.Name], groupOutboundPerSubscription) } @@ -238,11 +246,11 @@ func groupJoin(outbounds []boxOption.Outbound, groupTag string, appendFront bool } groupOutbound := outbounds[groupIndex] var outboundPtr *[]string - switch groupOutbound.Type { - case C.TypeSelector: - outboundPtr = &groupOutbound.SelectorOptions.Outbounds - case C.TypeURLTest: - outboundPtr = &groupOutbound.URLTestOptions.Outbounds + switch outboundOptions := groupOutbound.Options.(type) { + case *boxOption.SelectorOutboundOptions: + outboundPtr = &outboundOptions.Outbounds + case *boxOption.URLTestOutboundOptions: + outboundPtr = &outboundOptions.Outbounds default: panic(F.ToString("unexpected group type: ", groupOutbound.Type)) } diff --git a/template/render_route.go b/template/render_route.go index 02f62af..1e9b1ed 100644 --- a/template/render_route.go +++ b/template/render_route.go @@ -24,23 +24,34 @@ func (t *Template) renderRoute(metadata M.Metadata, options *option.Options) err { Type: C.RuleTypeLogical, LogicalOptions: option.LogicalRule{ - Mode: C.LogicalTypeOr, - Rules: []option.Rule{ - { - Type: C.RuleTypeDefault, - DefaultOptions: option.DefaultRule{ - Network: []string{N.NetworkUDP}, - Port: []uint16{53}, + RawLogicalRule: option.RawLogicalRule{ + Mode: C.LogicalTypeOr, + Rules: []option.Rule{ + { + Type: C.RuleTypeDefault, + DefaultOptions: option.DefaultRule{ + RawDefaultRule: option.RawDefaultRule{ + Network: []string{N.NetworkUDP}, + Port: []uint16{53}, + }, + }, }, - }, - { - Type: C.RuleTypeDefault, - DefaultOptions: option.DefaultRule{ - Protocol: []string{C.ProtocolDNS}, + { + Type: C.RuleTypeDefault, + DefaultOptions: option.DefaultRule{ + RawDefaultRule: option.RawDefaultRule{ + Protocol: []string{C.ProtocolDNS}, + }, + }, }, }, }, - Outbound: DNSTag, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.RouteActionOptions{ + Outbound: DNSTag, + }, + }, }, }, } @@ -56,16 +67,30 @@ func (t *Template) renderRoute(metadata M.Metadata, options *option.Options) err options.Route.Rules = append(options.Route.Rules, option.Rule{ Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - GeoIP: []string{"private"}, - Outbound: directTag, + RawDefaultRule: option.RawDefaultRule{ + GeoIP: []string{"private"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.RouteActionOptions{ + Outbound: directTag, + }, + }, }, }) } else { options.Route.Rules = append(options.Route.Rules, option.Rule{ Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - IPIsPrivate: true, - Outbound: directTag, + RawDefaultRule: option.RawDefaultRule{ + IPIsPrivate: true, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.RouteActionOptions{ + Outbound: directTag, + }, + }, }, }) } @@ -81,14 +106,28 @@ func (t *Template) renderRoute(metadata M.Metadata, options *option.Options) err options.Route.Rules = append(options.Route.Rules, option.Rule{ Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - ClashMode: modeGlobal, - Outbound: defaultTag, + RawDefaultRule: option.RawDefaultRule{ + ClashMode: modeGlobal, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.RouteActionOptions{ + Outbound: defaultTag, + }, + }, }, }, option.Rule{ Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - ClashMode: modeDirect, - Outbound: directTag, + RawDefaultRule: option.RawDefaultRule{ + ClashMode: modeDirect, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.RouteActionOptions{ + Outbound: directTag, + }, + }, }, }) } @@ -99,17 +138,31 @@ func (t *Template) renderRoute(metadata M.Metadata, options *option.Options) err options.Route.Rules = append(options.Route.Rules, option.Rule{ Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - GeoIP: []string{"cn"}, - Geosite: []string{"geolocation-cn"}, - Outbound: directTag, + RawDefaultRule: option.RawDefaultRule{ + GeoIP: []string{"cn"}, + Geosite: []string{"geolocation-cn"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.RouteActionOptions{ + Outbound: directTag, + }, + }, }, }) } else { options.Route.Rules = append(options.Route.Rules, option.Rule{ Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ - RuleSet: []string{"geoip-cn", "geosite-geolocation-cn"}, - Outbound: directTag, + RawDefaultRule: option.RawDefaultRule{ + RuleSet: []string{"geoip-cn", "geosite-geolocation-cn"}, + }, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.RouteActionOptions{ + Outbound: directTag, + }, + }, }, }) } @@ -125,17 +178,26 @@ func (t *Template) renderRoute(metadata M.Metadata, options *option.Options) err options.Route.Rules = append(options.Route.Rules, option.Rule{ Type: C.RuleTypeLogical, LogicalOptions: option.LogicalRule{ - Mode: C.LogicalTypeOr, - Rules: []option.Rule{ - { - Type: C.RuleTypeDefault, - DefaultOptions: option.DefaultRule{ - Network: []string{N.NetworkUDP}, - Port: []uint16{443}, + RawLogicalRule: option.RawLogicalRule{ + Mode: C.LogicalTypeOr, + Rules: []option.Rule{ + { + Type: C.RuleTypeDefault, + DefaultOptions: option.DefaultRule{ + RawDefaultRule: option.RawDefaultRule{ + Network: []string{N.NetworkUDP}, + Port: []uint16{443}, + }, + }, }, }, }, - Outbound: blockTag, + RuleAction: option.RuleAction{ + Action: C.RuleActionTypeRoute, + RouteOptions: option.RouteActionOptions{ + Outbound: blockTag, + }, + }, }, }) } diff --git a/template/template.go b/template/template.go index d707714..da04c96 100644 --- a/template/template.go +++ b/template/template.go @@ -1,6 +1,7 @@ package template import ( + "context" "regexp" M "github.com/sagernet/serenity/common/metadata" @@ -39,7 +40,7 @@ type ExtraGroup struct { exclude []*regexp.Regexp } -func (t *Template) Render(metadata M.Metadata, profileName string, outbounds [][]boxOption.Outbound, subscriptions []*subscription.Subscription) (*boxOption.Options, error) { +func (t *Template) Render(ctx context.Context, metadata M.Metadata, profileName string, outbounds [][]boxOption.Outbound, subscriptions []*subscription.Subscription) (*boxOption.Options, error) { var options boxOption.Options options.Log = t.Log err := t.renderDNS(metadata, &options) @@ -58,7 +59,7 @@ func (t *Template) Render(metadata M.Metadata, profileName string, outbounds [][ if err != nil { return nil, E.Cause(err, "render outbounds") } - err = t.renderExperimental(metadata, &options, profileName) + err = t.renderExperimental(ctx, metadata, &options, profileName) if err != nil { return nil, E.Cause(err, "render experimental") }