forked from mirror/serenity
Update dependencies
This commit is contained in:
parent
4f768e630d
commit
d2f1118c2e
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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())
|
||||
}
|
||||
|
31
go.mod
31
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
|
||||
|
66
go.sum
66
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=
|
||||
|
@ -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,7 +17,7 @@ type _Options struct {
|
||||
TLS *option.InboundTLSOptions `json:"tls,omitempty"`
|
||||
CacheFile string `json:"cache_file,omitempty"`
|
||||
|
||||
Outbounds []option.Listable[option.Outbound] `json:"outbounds,omitempty"`
|
||||
Outbounds []badoption.Listable[option.Outbound] `json:"outbounds,omitempty"`
|
||||
Subscriptions []Subscription `json:"subscriptions,omitempty"`
|
||||
Templates []Template `json:"templates,omitempty"`
|
||||
Profiles []Profile `json:"profiles,omitempty"`
|
||||
@ -24,8 +26,8 @@ type _Options struct {
|
||||
|
||||
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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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, "]")
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -110,10 +110,17 @@ func (t *Template) renderDNS(metadata M.Metadata, options *option.Options) error
|
||||
{
|
||||
Type: C.RuleTypeDefault,
|
||||
DefaultOptions: option.DefaultDNSRule{
|
||||
RawDefaultDNSRule: option.RawDefaultDNSRule{
|
||||
Outbound: []string{"any"},
|
||||
},
|
||||
DNSRuleAction: option.DNSRuleAction{
|
||||
Action: C.RuleActionTypeRoute,
|
||||
RouteOptions: option.DNSRouteActionOptions{
|
||||
Server: DNSLocalTag,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
clashModeRule := t.ClashModeRule
|
||||
if clashModeRule == "" {
|
||||
@ -132,15 +139,29 @@ 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{
|
||||
RawDefaultDNSRule: option.RawDefaultDNSRule{
|
||||
ClashMode: clashModeGlobal,
|
||||
},
|
||||
DNSRuleAction: option.DNSRuleAction{
|
||||
Action: C.RuleActionTypeRoute,
|
||||
RouteOptions: option.DNSRouteActionOptions{
|
||||
Server: DNSDefaultTag,
|
||||
},
|
||||
},
|
||||
},
|
||||
}, option.DNSRule{
|
||||
Type: C.RuleTypeDefault,
|
||||
DefaultOptions: option.DefaultDNSRule{
|
||||
RawDefaultDNSRule: option.RawDefaultDNSRule{
|
||||
ClashMode: clashModeDirect,
|
||||
},
|
||||
DNSRuleAction: option.DNSRuleAction{
|
||||
Action: C.RuleActionTypeRoute,
|
||||
RouteOptions: option.DNSRouteActionOptions{
|
||||
Server: DNSLocalTag,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
options.DNS.Rules = append(options.DNS.Rules, t.PreDNSRules...)
|
||||
@ -150,47 +171,90 @@ 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{
|
||||
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{
|
||||
RawDefaultDNSRule: option.RawDefaultDNSRule{
|
||||
RuleSet: []string{"geosite-geolocation-cn"},
|
||||
},
|
||||
DNSRuleAction: option.DNSRuleAction{
|
||||
Action: C.RuleActionTypeRoute,
|
||||
RouteOptions: option.DNSRouteActionOptions{
|
||||
Server: DNSLocalTag,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
if !t.DisableDNSLeak && (metadata.Version == nil || metadata.Version.GreaterThanOrEqual(semver.ParseVersion("1.9.0-alpha.1"))) {
|
||||
options.DNS.Rules = append(options.DNS.Rules, option.DNSRule{
|
||||
Type: C.RuleTypeDefault,
|
||||
DefaultOptions: option.DefaultDNSRule{
|
||||
RawDefaultDNSRule: option.RawDefaultDNSRule{
|
||||
ClashMode: clashModeRule,
|
||||
},
|
||||
DNSRuleAction: option.DNSRuleAction{
|
||||
Action: C.RuleActionTypeRoute,
|
||||
RouteOptions: option.DNSRouteActionOptions{
|
||||
Server: DNSDefaultTag,
|
||||
},
|
||||
},
|
||||
},
|
||||
}, option.DNSRule{
|
||||
Type: C.RuleTypeLogical,
|
||||
LogicalOptions: option.LogicalDNSRule{
|
||||
RawLogicalDNSRule: option.RawLogicalDNSRule{
|
||||
Mode: C.LogicalTypeAnd,
|
||||
Rules: []option.DNSRule{
|
||||
{
|
||||
Type: C.RuleTypeDefault,
|
||||
DefaultOptions: option.DefaultDNSRule{
|
||||
RawDefaultDNSRule: option.RawDefaultDNSRule{
|
||||
RuleSet: []string{"geosite-geolocation-!cn"},
|
||||
Invert: true,
|
||||
},
|
||||
DNSRuleAction: option.DNSRuleAction{
|
||||
Action: C.RuleActionTypeRoute,
|
||||
RouteOptions: option.DNSRouteActionOptions{
|
||||
Server: DNSDefaultTag,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: C.RuleTypeDefault,
|
||||
DefaultOptions: option.DefaultDNSRule{
|
||||
RawDefaultDNSRule: option.RawDefaultDNSRule{
|
||||
RuleSet: []string{"geoip-cn"},
|
||||
},
|
||||
},
|
||||
},
|
||||
DNSRuleAction: option.DNSRuleAction{
|
||||
Action: C.RuleActionTypeRoute,
|
||||
RouteOptions: option.DNSRouteActionOptions{
|
||||
Server: DNSLocalTag,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
DNSRuleAction: option.DNSRuleAction{
|
||||
Action: C.RuleActionTypeRoute,
|
||||
RouteOptions: option.DNSRouteActionOptions{
|
||||
Server: DNSLocalTag,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -201,12 +265,19 @@ 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{
|
||||
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,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
return nil
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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{
|
||||
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,18 +79,16 @@ 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{
|
||||
mixedOptions := &option.HTTPMixedInboundOptions{
|
||||
ListenOptions: option.ListenOptions{
|
||||
Listen: option.NewListenAddress(netip.AddrFrom4([4]byte{127, 0, 0, 1})),
|
||||
ListenPort: DefaultMixedPort,
|
||||
@ -98,14 +98,17 @@ func (t *Template) renderInbounds(metadata M.Metadata, options *option.Options)
|
||||
},
|
||||
},
|
||||
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)
|
||||
}
|
||||
|
@ -33,20 +33,22 @@ func (t *Template) renderOutbounds(metadata M.Metadata, options *boxOption.Optio
|
||||
{
|
||||
Tag: directTag,
|
||||
Type: C.TypeDirect,
|
||||
DirectOptions: common.PtrValueOrDefault(t.CustomDirect),
|
||||
Options: common.Ptr(common.PtrValueOrDefault(t.CustomDirect)),
|
||||
},
|
||||
{
|
||||
Tag: blockTag,
|
||||
Type: C.TypeBlock,
|
||||
Options: &boxOption.StubOptions{},
|
||||
},
|
||||
{
|
||||
Tag: DNSTag,
|
||||
Type: C.TypeDNS,
|
||||
Options: &boxOption.StubOptions{},
|
||||
},
|
||||
{
|
||||
Tag: defaultTag,
|
||||
Type: C.TypeSelector,
|
||||
SelectorOptions: common.PtrValueOrDefault(t.CustomSelector),
|
||||
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),
|
||||
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),
|
||||
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)
|
||||
}
|
||||
@ -146,14 +150,16 @@ func (t *Template) renderOutbounds(metadata M.Metadata, options *boxOption.Optio
|
||||
groupOutbound := boxOption.Outbound{
|
||||
Tag: extraGroup.Tag,
|
||||
Type: extraGroup.Type,
|
||||
SelectorOptions: common.PtrValueOrDefault(extraGroup.CustomSelector),
|
||||
URLTestOptions: common.PtrValueOrDefault(extraGroup.CustomURLTest),
|
||||
}
|
||||
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)
|
||||
@ -193,14 +199,16 @@ func (t *Template) renderOutbounds(metadata M.Metadata, options *boxOption.Optio
|
||||
groupOutboundPerSubscription := boxOption.Outbound{
|
||||
Tag: tagPerSubscription,
|
||||
Type: extraGroup.Type,
|
||||
SelectorOptions: common.PtrValueOrDefault(extraGroup.CustomSelector),
|
||||
URLTestOptions: common.PtrValueOrDefault(extraGroup.CustomURLTest),
|
||||
}
|
||||
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))
|
||||
}
|
||||
|
@ -24,25 +24,36 @@ func (t *Template) renderRoute(metadata M.Metadata, options *option.Options) err
|
||||
{
|
||||
Type: C.RuleTypeLogical,
|
||||
LogicalOptions: option.LogicalRule{
|
||||
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{
|
||||
RawDefaultRule: option.RawDefaultRule{
|
||||
Protocol: []string{C.ProtocolDNS},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
RuleAction: option.RuleAction{
|
||||
Action: C.RuleActionTypeRoute,
|
||||
RouteOptions: option.RouteActionOptions{
|
||||
Outbound: DNSTag,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
directTag := t.DirectTag
|
||||
defaultTag := t.DefaultTag
|
||||
@ -56,17 +67,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{
|
||||
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{
|
||||
RawDefaultRule: option.RawDefaultRule{
|
||||
IPIsPrivate: true,
|
||||
},
|
||||
RuleAction: option.RuleAction{
|
||||
Action: C.RuleActionTypeRoute,
|
||||
RouteOptions: option.RouteActionOptions{
|
||||
Outbound: directTag,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
if !t.DisableClashMode {
|
||||
@ -81,15 +106,29 @@ 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{
|
||||
RawDefaultRule: option.RawDefaultRule{
|
||||
ClashMode: modeGlobal,
|
||||
},
|
||||
RuleAction: option.RuleAction{
|
||||
Action: C.RuleActionTypeRoute,
|
||||
RouteOptions: option.RouteActionOptions{
|
||||
Outbound: defaultTag,
|
||||
},
|
||||
},
|
||||
},
|
||||
}, option.Rule{
|
||||
Type: C.RuleTypeDefault,
|
||||
DefaultOptions: option.DefaultRule{
|
||||
RawDefaultRule: option.RawDefaultRule{
|
||||
ClashMode: modeDirect,
|
||||
},
|
||||
RuleAction: option.RuleAction{
|
||||
Action: C.RuleActionTypeRoute,
|
||||
RouteOptions: option.RouteActionOptions{
|
||||
Outbound: directTag,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
options.Route.Rules = append(options.Route.Rules, t.PreRules...)
|
||||
@ -99,18 +138,32 @@ 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{
|
||||
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{
|
||||
RawDefaultRule: option.RawDefaultRule{
|
||||
RuleSet: []string{"geoip-cn", "geosite-geolocation-cn"},
|
||||
},
|
||||
RuleAction: option.RuleAction{
|
||||
Action: C.RuleActionTypeRoute,
|
||||
RouteOptions: option.RouteActionOptions{
|
||||
Outbound: directTag,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -125,18 +178,27 @@ 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{
|
||||
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},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
RuleAction: option.RuleAction{
|
||||
Action: C.RuleActionTypeRoute,
|
||||
RouteOptions: option.RouteActionOptions{
|
||||
Outbound: blockTag,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
return nil
|
||||
|
@ -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")
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user