diff --git a/common/convert.go b/common/convert.go index c62c0df..fbc6f49 100644 --- a/common/convert.go +++ b/common/convert.go @@ -15,6 +15,7 @@ import ( "github.com/nitezs/sub2sing-box/model" "github.com/nitezs/sub2sing-box/parser" "github.com/nitezs/sub2sing-box/util" + "github.com/sagernet/sing-box/option" ) func Convert( @@ -99,7 +100,7 @@ func Convert( if reg.MatchString(templateDate) || strings.Contains(templateDate, constant.AllCountryTags) || group { outbounds = AddCountryGroup(outbounds, groupType, sortKey, sortType) } - var template model.Config + var template model.Options if err = json.Unmarshal([]byte(templateDate), &template); err != nil { return "", err } @@ -129,20 +130,24 @@ func AddCountryGroup(proxies []model.Outbound, groupType string, sortKey string, } else { if groupType == C.TypeSelector || groupType == "" { newGroup[country] = model.Outbound{ - Tag: country, - Type: groupType, - SelectorOptions: model.SelectorOutboundOptions{ - Outbounds: []string{p.Tag}, - InterruptExistConnections: true, + Outbound: option.Outbound{ + Tag: country, + Type: groupType, + SelectorOptions: option.SelectorOutboundOptions{ + Outbounds: []string{p.Tag}, + InterruptExistConnections: true, + }, }, } } else if groupType == C.TypeURLTest { newGroup[country] = model.Outbound{ - Tag: country, - Type: groupType, - URLTestOptions: model.URLTestOutboundOptions{ - Outbounds: []string{p.Tag}, - InterruptExistConnections: true, + Outbound: option.Outbound{ + Tag: country, + Type: groupType, + URLTestOptions: option.URLTestOutboundOptions{ + Outbounds: []string{p.Tag}, + InterruptExistConnections: true, + }, }, } } @@ -200,7 +205,7 @@ func ReadTemplate(template string) (string, error) { } } -func MergeTemplate(outbounds []model.Outbound, template *model.Config) (string, error) { +func MergeTemplate(outbounds []model.Outbound, template *model.Options) (string, error) { var err error proxyTags := make([]string, 0) groupTags := make([]string, 0) diff --git a/go.mod b/go.mod index 5d7e233..22204de 100644 --- a/go.mod +++ b/go.mod @@ -3,38 +3,49 @@ module github.com/nitezs/sub2sing-box go 1.21.5 require ( - github.com/spf13/cobra v1.8.0 - golang.org/x/text v0.9.0 + github.com/sagernet/sing-box v1.10.0-beta.11 + github.com/spf13/cobra v1.8.1 + golang.org/x/text v0.18.0 ) require ( - github.com/bytedance/sonic v1.9.1 // indirect - github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect - github.com/gabriel-vasile/mimetype v1.4.2 // indirect + github.com/bytedance/sonic v1.12.3 // indirect + github.com/bytedance/sonic/loader v0.2.0 // indirect + github.com/cloudwego/base64x v0.1.4 // indirect + github.com/cloudwego/iasm v0.2.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.5 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.14.0 // indirect - github.com/goccy/go-json v0.10.2 // indirect + github.com/go-playground/validator/v10 v10.22.1 // indirect + github.com/goccy/go-json v0.10.3 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/cpuid/v2 v2.2.4 // indirect - github.com/leodido/go-urn v1.2.4 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect + github.com/klauspost/cpuid/v2 v2.2.8 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/miekg/dns v1.1.61 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pelletier/go-toml/v2 v2.0.8 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect + github.com/sagernet/sing v0.5.0-beta.2 // indirect + github.com/sagernet/sing-dns v0.3.0-beta.14 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect - github.com/ugorji/go/codec v1.2.11 // indirect - golang.org/x/arch v0.3.0 // indirect - golang.org/x/crypto v0.9.0 // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/sys v0.8.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect + github.com/ugorji/go/codec v1.2.12 // indirect + go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect + golang.org/x/arch v0.10.0 // indirect + golang.org/x/crypto v0.27.0 // indirect + golang.org/x/mod v0.19.0 // indirect + golang.org/x/net v0.29.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/tools v0.23.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) require ( - github.com/gin-gonic/gin v1.9.1 + github.com/gin-gonic/gin v1.10.0 github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect ) diff --git a/go.sum b/go.sum index be668a5..a5ea585 100644 --- a/go.sum +++ b/go.sum @@ -1,56 +1,84 @@ -github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= -github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= -github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= -github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= -github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= -github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/bytedance/sonic v1.12.3 h1:W2MGa7RCU1QTeYRTPE3+88mVC0yXmsRQRChiyVocVjU= +github.com/bytedance/sonic v1.12.3/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk= +github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM= +github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= +github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= +github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= -github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4= +github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= -github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= +github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= -github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= -github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= -github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA= +github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= +github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +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/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +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/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= -github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= -github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= -github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= +github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs= +github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= -github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +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/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= +github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= +github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs= +github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +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/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.11 h1:SBQtW1WPoNEmTvBCwzngSaFrYfYCqjO/J6CHLZd5S/Q= +github.com/sagernet/sing-box v1.10.0-beta.11/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/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= 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= @@ -61,34 +89,40 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= -github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= -golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= -golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= -golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= +github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +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/arch v0.10.0 h1:S3huipmSclq3PJMNe76NGwkBR504WFkQ5dhzWzP8ZW8= +golang.org/x/arch v0.10.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= +golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +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.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= +golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= diff --git a/model/config.go b/model/config.go deleted file mode 100644 index 3cdaec4..0000000 --- a/model/config.go +++ /dev/null @@ -1,102 +0,0 @@ -package model - -import "encoding/json" - -type Listable[T any] []T - -func (l *Listable[T]) UnmarshalJSON(data []byte) error { - var arr []T - if err := json.Unmarshal(data, &arr); err == nil { - *l = arr - return nil - } - var v T - if err := json.Unmarshal(data, &v); err == nil { - *l = []T{v} - return nil - } - return nil -} - -type Config struct { - Log any `json:"log,omitempty"` - DNS any `json:"dns,omitempty"` - NTP any `json:"ntp,omitempty"` - Inbounds any `json:"inbounds,omitempty"` - Outbounds []Outbound `json:"outbounds,omitempty"` - Route *RouteOptions `json:"route,omitempty"` - Experimental any `json:"experimental,omitempty"` -} - -type RouteOptions struct { - GeoIP *GeoIPOptions `json:"geoip,omitempty"` - Geosite *GeositeOptions `json:"geosite,omitempty"` - Rules Listable[Rule] `json:"rules,omitempty"` - RuleSet Listable[RuleSet] `json:"rule_set,omitempty"` - Final string `json:"final,omitempty"` - FindProcess bool `json:"find_process,omitempty"` - AutoDetectInterface bool `json:"auto_detect_interface,omitempty"` - OverrideAndroidVPN bool `json:"override_android_vpn,omitempty"` - DefaultInterface string `json:"default_interface,omitempty"` - DefaultMark int `json:"default_mark,omitempty"` -} - -type Rule struct { - Type string `json:"type,omitempty"` - Inbound Listable[string] `json:"inbound,omitempty"` - IPVersion int `json:"ip_version,omitempty"` - Network Listable[string] `json:"network,omitempty"` - AuthUser Listable[string] `json:"auth_user,omitempty"` - Protocol string `json:"protocol,omitempty"` - Domain Listable[string] `json:"domain,omitempty"` - DomainSuffix Listable[string] `json:"domain_suffix,omitempty"` - DomainKeyword Listable[string] `json:"domain_keyword,omitempty"` - DomainRegex Listable[string] `json:"domain_regex,omitempty"` - Geosite Listable[string] `json:"geosite,omitempty"` - SourceGeoIP Listable[string] `json:"source_geoip,omitempty"` - GeoIP Listable[string] `json:"geoip,omitempty"` - SourceIPCIDR Listable[string] `json:"source_ip_cidr,omitempty"` - SourceIPIsPrivate bool `json:"source_ip_is_private,omitempty"` - IPCIDR Listable[string] `json:"ip_cidr,omitempty"` - IPIsPrivate bool `json:"ip_is_private,omitempty"` - SourcePort Listable[uint16] `json:"source_port,omitempty"` - SourcePortRange Listable[string] `json:"source_port_range,omitempty"` - Port Listable[uint16] `json:"port,omitempty"` - PortRange Listable[string] `json:"port_range,omitempty"` - ProcessName Listable[string] `json:"process_name,omitempty"` - ProcessPath Listable[string] `json:"process_path,omitempty"` - PackageName Listable[string] `json:"package_name,omitempty"` - User Listable[string] `json:"user,omitempty"` - UserID Listable[int32] `json:"user_id,omitempty"` - ClashMode string `json:"clash_mode,omitempty"` - WIFISSID Listable[string] `json:"wifi_ssid,omitempty"` - WIFIBSSID Listable[string] `json:"wifi_bssid,omitempty"` - RuleSet Listable[string] `json:"rule_set,omitempty"` - RuleSetIPCIDRMatchSource bool `json:"rule_set_ipcidr_match_source,omitempty"` - Invert bool `json:"invert,omitempty"` - Outbound string `json:"outbound,omitempty"` - Mode string `json:"mode,omitempty"` - Rules Listable[Rule] `json:"rules,omitempty"` -} - -type GeoIPOptions struct { - Path string `json:"path,omitempty"` - DownloadURL string `json:"download_url,omitempty"` - DownloadDetour string `json:"download_detour,omitempty"` -} - -type GeositeOptions struct { - Path string `json:"path,omitempty"` - DownloadURL string `json:"download_url,omitempty"` - DownloadDetour string `json:"download_detour,omitempty"` -} - -type RuleSet struct { - Type string `json:"type"` - Tag string `json:"tag"` - Format string `json:"format"` - Path string `json:"path,omitempty"` - URL string `json:"url"` - DownloadDetour string `json:"download_detour,omitempty"` - UpdateInterval string `json:"update_interval,omitempty"` -} diff --git a/model/direct.go b/model/direct.go deleted file mode 100644 index 64464b6..0000000 --- a/model/direct.go +++ /dev/null @@ -1,8 +0,0 @@ -package model - -type DirectOutboundOptions struct { - DialerOptions - OverrideAddress string `json:"override_address,omitempty"` - OverridePort uint16 `json:"override_port,omitempty"` - ProxyProtocol uint8 `json:"proxy_protocol,omitempty"` -} diff --git a/model/group.go b/model/group.go deleted file mode 100644 index aa0511b..0000000 --- a/model/group.go +++ /dev/null @@ -1,16 +0,0 @@ -package model - -type SelectorOutboundOptions struct { - Outbounds []string `json:"outbounds"` - Default string `json:"default,omitempty"` - InterruptExistConnections bool `json:"interrupt_exist_connections,omitempty"` -} - -type URLTestOutboundOptions struct { - Outbounds []string `json:"outbounds"` - URL string `json:"url,omitempty"` - Interval string `json:"interval,omitempty"` - Tolerance uint16 `json:"tolerance,omitempty"` - IdleTimeout string `json:"idle_timeout,omitempty"` - InterruptExistConnections bool `json:"interrupt_exist_connections,omitempty"` -} diff --git a/model/hysteria.go b/model/hysteria.go deleted file mode 100644 index 91d0e73..0000000 --- a/model/hysteria.go +++ /dev/null @@ -1,18 +0,0 @@ -package model - -type HysteriaOutboundOptions struct { - DialerOptions - ServerOptions - Up string `json:"up,omitempty"` - UpMbps int `json:"up_mbps,omitempty"` - Down string `json:"down,omitempty"` - DownMbps int `json:"down_mbps,omitempty"` - Obfs string `json:"obfs,omitempty"` - Auth []byte `json:"auth,omitempty"` - AuthString string `json:"auth_str,omitempty"` - ReceiveWindowConn uint64 `json:"recv_window_conn,omitempty"` - ReceiveWindow uint64 `json:"recv_window,omitempty"` - DisableMTUDiscovery bool `json:"disable_mtu_discovery,omitempty"` - Network string `json:"network,omitempty"` - OutboundTLSOptionsContainer -} diff --git a/model/hysteria2.go b/model/hysteria2.go deleted file mode 100644 index 5a2f117..0000000 --- a/model/hysteria2.go +++ /dev/null @@ -1,18 +0,0 @@ -package model - -type Hysteria2Obfs struct { - Type string `json:"type,omitempty"` - Password string `json:"password,omitempty"` -} - -type Hysteria2OutboundOptions struct { - DialerOptions - ServerOptions - UpMbps int `json:"up_mbps,omitempty"` - DownMbps int `json:"down_mbps,omitempty"` - Obfs *Hysteria2Obfs `json:"obfs,omitempty"` - Password string `json:"password,omitempty"` - Network string `json:"network,omitempty"` - OutboundTLSOptionsContainer - BrutalDebug bool `json:"brutal_debug,omitempty"` -} diff --git a/model/multiplex.go b/model/multiplex.go deleted file mode 100644 index e7f6332..0000000 --- a/model/multiplex.go +++ /dev/null @@ -1,17 +0,0 @@ -package model - -type OutboundMultiplexOptions struct { - Enabled bool `json:"enabled,omitempty"` - Protocol string `json:"protocol,omitempty"` - MaxConnections int `json:"max_connections,omitempty"` - MinStreams int `json:"min_streams,omitempty"` - MaxStreams int `json:"max_streams,omitempty"` - Padding bool `json:"padding,omitempty"` - Brutal *BrutalOptions `json:"brutal,omitempty"` -} - -type BrutalOptions struct { - Enabled bool `json:"enabled,omitempty"` - UpMbps int `json:"up_mbps,omitempty"` - DownMbps int `json:"down_mbps,omitempty"` -} diff --git a/model/option.go b/model/option.go new file mode 100644 index 0000000..e86e005 --- /dev/null +++ b/model/option.go @@ -0,0 +1,41 @@ +package model + +import ( + "bytes" + "encoding/json" + + "github.com/sagernet/sing-box/option" +) + +type _Options struct { + RawMessage json.RawMessage `json:"-"` + Schema string `json:"$schema,omitempty"` + Log *LogOptions `json:"log,omitempty"` + DNS *option.DNSOptions `json:"dns,omitempty"` + NTP *option.NTPOptions `json:"ntp,omitempty"` + Inbounds []option.Inbound `json:"inbounds,omitempty"` + Outbounds []Outbound `json:"outbounds,omitempty"` + Route *option.RouteOptions `json:"route,omitempty"` + Experimental *option.ExperimentalOptions `json:"experimental,omitempty"` +} + +type Options _Options + +func (o *Options) UnmarshalJSON(content []byte) error { + decoder := json.NewDecoder(bytes.NewReader(content)) + decoder.DisallowUnknownFields() + err := decoder.Decode((*_Options)(o)) + if err != nil { + return err + } + o.RawMessage = content + return nil +} + +type LogOptions struct { + Disabled bool `json:"disabled,omitempty"` + Level string `json:"level,omitempty"` + Output string `json:"output,omitempty"` + Timestamp bool `json:"timestamp,omitempty"` + DisableColor bool `json:"-"` +} diff --git a/model/outbound.go b/model/outbound.go index 6a75fc6..8a21c92 100644 --- a/model/outbound.go +++ b/model/outbound.go @@ -1,155 +1,12 @@ package model import ( - "encoding/json" - "errors" - "reflect" - "strings" - C "github.com/nitezs/sub2sing-box/constant" + "github.com/sagernet/sing-box/option" ) -type _Outbound struct { - Type string `json:"type"` - Tag string `json:"tag,omitempty"` - DirectOptions DirectOutboundOptions `json:"-"` - SocksOptions SocksOutboundOptions `json:"-"` - HTTPOptions HTTPOutboundOptions `json:"-"` - ShadowsocksOptions ShadowsocksOutboundOptions `json:"-"` - VMessOptions VMessOutboundOptions `json:"-"` - TrojanOptions TrojanOutboundOptions `json:"-"` - WireGuardOptions WireGuardOutboundOptions `json:"-"` - HysteriaOptions HysteriaOutboundOptions `json:"-"` - TorOptions TorOutboundOptions `json:"-"` - SSHOptions SSHOutboundOptions `json:"-"` - ShadowTLSOptions ShadowTLSOutboundOptions `json:"-"` - ShadowsocksROptions ShadowsocksROutboundOptions `json:"-"` - VLESSOptions VLESSOutboundOptions `json:"-"` - TUICOptions TUICOutboundOptions `json:"-"` - Hysteria2Options Hysteria2OutboundOptions `json:"-"` - SelectorOptions SelectorOutboundOptions `json:"-"` - URLTestOptions URLTestOutboundOptions `json:"-"` -} -type Outbound _Outbound - -func (h *Outbound) RawOptions() (any, error) { - var rawOptionsPtr any - switch h.Type { - case C.TypeDirect: - rawOptionsPtr = &h.DirectOptions - case C.TypeBlock, C.TypeDNS: - rawOptionsPtr = nil - case C.TypeSOCKS: - rawOptionsPtr = &h.SocksOptions - case C.TypeHTTP: - rawOptionsPtr = &h.HTTPOptions - case C.TypeShadowsocks: - rawOptionsPtr = &h.ShadowsocksOptions - case C.TypeVMess: - rawOptionsPtr = &h.VMessOptions - case C.TypeTrojan: - rawOptionsPtr = &h.TrojanOptions - case C.TypeWireGuard: - rawOptionsPtr = &h.WireGuardOptions - case C.TypeHysteria: - rawOptionsPtr = &h.HysteriaOptions - case C.TypeTor: - rawOptionsPtr = &h.TorOptions - case C.TypeSSH: - rawOptionsPtr = &h.SSHOptions - case C.TypeShadowTLS: - rawOptionsPtr = &h.ShadowTLSOptions - case C.TypeShadowsocksR: - rawOptionsPtr = &h.ShadowsocksROptions - case C.TypeVLESS: - rawOptionsPtr = &h.VLESSOptions - case C.TypeTUIC: - rawOptionsPtr = &h.TUICOptions - case C.TypeHysteria2: - rawOptionsPtr = &h.Hysteria2Options - case C.TypeSelector: - rawOptionsPtr = &h.SelectorOptions - case C.TypeURLTest: - rawOptionsPtr = &h.URLTestOptions - case "": - return nil, errors.New("missing outbound type") - default: - return nil, errors.New("unknown outbound type: " + h.Type) - } - return rawOptionsPtr, nil -} - -func (h *Outbound) MarshalJSON() ([]byte, error) { - rawOptions, err := h.RawOptions() - if err != nil { - return nil, err - } - if rawOptions == nil { - return json.Marshal((*_Outbound)(h)) - } - result := make(map[string]any) - result["type"] = h.Type - result["tag"] = h.Tag - optsValue := reflect.ValueOf(rawOptions).Elem() - optsType := optsValue.Type() - for i := 0; i < optsType.NumField(); i++ { - field := optsValue.Field(i) - fieldType := optsType.Field(i) - if fieldType.Anonymous { - embeddedFields := reflect.ValueOf(field.Interface()) - if field.Kind() == reflect.Struct { - for j := 0; j < embeddedFields.NumField(); j++ { - embeddedField := embeddedFields.Field(j) - embeddedFieldType := embeddedFields.Type().Field(j) - processField(embeddedField, embeddedFieldType, result) - } - } - } else { - processField(field, fieldType, result) - } - } - return json.Marshal(result) -} - -func processField(field reflect.Value, fieldType reflect.StructField, result map[string]any) { - jsonTag := fieldType.Tag.Get("json") - if jsonTag == "-" { - return - } - tagParts := strings.Split(jsonTag, ",") - tagName := tagParts[0] - if len(tagParts) > 1 && tagParts[1] == "omitempty" && field.IsZero() { - return - } - result[tagName] = field.Interface() -} - -func (h *Outbound) UnmarshalJSON(bytes []byte) error { - err := json.Unmarshal(bytes, (*_Outbound)(h)) - if err != nil { - return err - } - rawOptions, err := h.RawOptions() - if err != nil { - return err - } - if rawOptions == nil { - return nil - } - err = json.Unmarshal(bytes, rawOptions) - if err != nil { - return err - } - rawOptionsType := reflect.TypeOf(rawOptions).Elem() - hValue := reflect.ValueOf(h).Elem() - for i := 0; i < hValue.NumField(); i++ { - fieldType := hValue.Field(i).Type() - if fieldType == rawOptionsType { - hValue.Field(i).Set(reflect.ValueOf(rawOptions).Elem()) - return nil - } - } - return errors.New("unknown outbound type: " + h.Type) +type Outbound struct { + option.Outbound } func (h *Outbound) GetOutbounds() []string { @@ -170,26 +27,3 @@ func (h *Outbound) SetOutbounds(outbounds []string) { h.URLTestOptions.Outbounds = outbounds } } - -type DialerOptions struct { - Detour string `json:"detour,omitempty"` - BindInterface string `json:"bind_interface,omitempty"` - Inet4BindAddress string `json:"inet4_bind_address,omitempty"` - Inet6BindAddress string `json:"inet6_bind_address,omitempty"` - ProtectPath string `json:"protect_path,omitempty"` - RoutingMark int `json:"routing_mark,omitempty"` - ReuseAddr bool `json:"reuse_addr,omitempty"` - ConnectTimeout string `json:"connect_timeout,omitempty"` - TCPFastOpen bool `json:"tcp_fast_open,omitempty"` - TCPMultiPath bool `json:"tcp_multi_path,omitempty"` - UDPFragment *bool `json:"udp_fragment,omitempty"` - UDPFragmentDefault bool `json:"-"` - DomainStrategy string `json:"domain_strategy,omitempty"` - FallbackDelay string `json:"fallback_delay,omitempty"` - IsWireGuardListener bool `json:"-"` -} - -type ServerOptions struct { - Server string `json:"server"` - ServerPort uint16 `json:"server_port"` -} diff --git a/model/shadowsocks.go b/model/shadowsocks.go deleted file mode 100644 index 038de5e..0000000 --- a/model/shadowsocks.go +++ /dev/null @@ -1,13 +0,0 @@ -package model - -type ShadowsocksOutboundOptions struct { - DialerOptions - ServerOptions - Method string `json:"method"` - Password string `json:"password"` - Plugin string `json:"plugin,omitempty"` - PluginOptions string `json:"plugin_opts,omitempty"` - Network string `json:"network,omitempty"` - UDPOverTCP *UDPOverTCPOptions `json:"udp_over_tcp,omitempty"` - Multiplex *OutboundMultiplexOptions `json:"multiplex,omitempty"` -} diff --git a/model/shadowsocksr.go b/model/shadowsocksr.go deleted file mode 100644 index 7cbc051..0000000 --- a/model/shadowsocksr.go +++ /dev/null @@ -1,13 +0,0 @@ -package model - -type ShadowsocksROutboundOptions struct { - DialerOptions - ServerOptions - Method string `json:"method"` - Password string `json:"password"` - Obfs string `json:"obfs,omitempty"` - ObfsParam string `json:"obfs_param,omitempty"` - Protocol string `json:"protocol,omitempty"` - ProtocolParam string `json:"protocol_param,omitempty"` - Network string `json:"network,omitempty"` -} diff --git a/model/shadowtls.go b/model/shadowtls.go deleted file mode 100644 index 30cd488..0000000 --- a/model/shadowtls.go +++ /dev/null @@ -1,19 +0,0 @@ -package model - -type ShadowTLSUser struct { - Name string `json:"name,omitempty"` - Password string `json:"password,omitempty"` -} - -type ShadowTLSHandshakeOptions struct { - ServerOptions - DialerOptions -} - -type ShadowTLSOutboundOptions struct { - DialerOptions - ServerOptions - Version int `json:"version,omitempty"` - Password string `json:"password,omitempty"` - OutboundTLSOptionsContainer -} diff --git a/model/simple.go b/model/simple.go deleted file mode 100644 index adf7439..0000000 --- a/model/simple.go +++ /dev/null @@ -1,21 +0,0 @@ -package model - -type SocksOutboundOptions struct { - DialerOptions - ServerOptions - Version string `json:"version,omitempty"` - Username string `json:"username,omitempty"` - Password string `json:"password,omitempty"` - Network Listable[string] `json:"network,omitempty"` - UDPOverTCP *UDPOverTCPOptions `json:"udp_over_tcp,omitempty"` -} - -type HTTPOutboundOptions struct { - DialerOptions - ServerOptions - Username string `json:"username,omitempty"` - Password string `json:"password,omitempty"` - OutboundTLSOptionsContainer - Path string `json:"path,omitempty"` - Headers map[string]string `json:"headers,omitempty"` -} diff --git a/model/ssh.go b/model/ssh.go deleted file mode 100644 index 3aa962f..0000000 --- a/model/ssh.go +++ /dev/null @@ -1,14 +0,0 @@ -package model - -type SSHOutboundOptions struct { - DialerOptions - ServerOptions - User string `json:"user,omitempty"` - Password string `json:"password,omitempty"` - PrivateKey Listable[string] `json:"private_key,omitempty"` - PrivateKeyPath string `json:"private_key_path,omitempty"` - PrivateKeyPassphrase string `json:"private_key_passphrase,omitempty"` - HostKey Listable[string] `json:"host_key,omitempty"` - HostKeyAlgorithms Listable[string] `json:"host_key_algorithms,omitempty"` - ClientVersion string `json:"client_version,omitempty"` -} diff --git a/model/tls.go b/model/tls.go deleted file mode 100644 index 64426de..0000000 --- a/model/tls.go +++ /dev/null @@ -1,40 +0,0 @@ -package model - -type OutboundTLSOptions struct { - Enabled bool `json:"enabled,omitempty"` - DisableSNI bool `json:"disable_sni,omitempty"` - ServerName string `json:"server_name,omitempty"` - Insecure bool `json:"insecure,omitempty"` - ALPN Listable[string] `json:"alpn,omitempty"` - MinVersion string `json:"min_version,omitempty"` - MaxVersion string `json:"max_version,omitempty"` - CipherSuites Listable[string] `json:"cipher_suites,omitempty"` - Certificate Listable[string] `json:"certificate,omitempty"` - CertificatePath string `json:"certificate_path,omitempty"` - ECH *OutboundECHOptions `json:"ech,omitempty"` - UTLS *OutboundUTLSOptions `json:"utls,omitempty"` - Reality *OutboundRealityOptions `json:"reality,omitempty"` -} - -type OutboundECHOptions struct { - Enabled bool `json:"enabled,omitempty"` - PQSignatureSchemesEnabled bool `json:"pq_signature_schemes_enabled,omitempty"` - DynamicRecordSizingDisabled bool `json:"dynamic_record_sizing_disabled,omitempty"` - Config Listable[string] `json:"config,omitempty"` - ConfigPath string `json:"config_path,omitempty"` -} - -type OutboundUTLSOptions struct { - Enabled bool `json:"enabled,omitempty"` - Fingerprint string `json:"fingerprint,omitempty"` -} - -type OutboundRealityOptions struct { - Enabled bool `json:"enabled,omitempty"` - PublicKey string `json:"public_key,omitempty"` - ShortID string `json:"short_id,omitempty"` -} - -type OutboundTLSOptionsContainer struct { - TLS *OutboundTLSOptions `json:"tls,omitempty"` -} diff --git a/model/tor.go b/model/tor.go deleted file mode 100644 index 4e04421..0000000 --- a/model/tor.go +++ /dev/null @@ -1,9 +0,0 @@ -package model - -type TorOutboundOptions struct { - DialerOptions - ExecutablePath string `json:"executable_path,omitempty"` - ExtraArgs []string `json:"extra_args,omitempty"` - DataDirectory string `json:"data_directory,omitempty"` - Options map[string]string `json:"torrc,omitempty"` -} diff --git a/model/trojan.go b/model/trojan.go deleted file mode 100644 index a1176c0..0000000 --- a/model/trojan.go +++ /dev/null @@ -1,11 +0,0 @@ -package model - -type TrojanOutboundOptions struct { - DialerOptions - ServerOptions - Password string `json:"password"` - Network string `json:"network,omitempty"` - OutboundTLSOptionsContainer - Multiplex *OutboundMultiplexOptions `json:"multiplex,omitempty"` - Transport *V2RayTransportOptions `json:"transport,omitempty"` -} diff --git a/model/tuic.go b/model/tuic.go deleted file mode 100644 index 6cf3c91..0000000 --- a/model/tuic.go +++ /dev/null @@ -1,15 +0,0 @@ -package model - -type TUICOutboundOptions struct { - DialerOptions - ServerOptions - UUID string `json:"uuid,omitempty"` - Password string `json:"password,omitempty"` - CongestionControl string `json:"congestion_control,omitempty"` - UDPRelayMode string `json:"udp_relay_mode,omitempty"` - UDPOverStream bool `json:"udp_over_stream,omitempty"` - ZeroRTTHandshake bool `json:"zero_rtt_handshake,omitempty"` - Heartbeat string `json:"heartbeat,omitempty"` - Network string `json:"network,omitempty"` - OutboundTLSOptionsContainer -} diff --git a/model/udp_over_tcp.go b/model/udp_over_tcp.go deleted file mode 100644 index 86dbf6b..0000000 --- a/model/udp_over_tcp.go +++ /dev/null @@ -1,6 +0,0 @@ -package model - -type UDPOverTCPOptions struct { - Enabled bool `json:"enabled,omitempty"` - Version uint8 `json:"version,omitempty"` -} diff --git a/model/v2ray_transport.go b/model/v2ray_transport.go deleted file mode 100644 index 46ac7a6..0000000 --- a/model/v2ray_transport.go +++ /dev/null @@ -1,85 +0,0 @@ -package model - -import ( - "encoding/json" -) - -type V2RayTransportOptions struct { - Type string `json:"type"` - HTTPOptions V2RayHTTPOptions `json:"-"` - WebsocketOptions V2RayWebsocketOptions `json:"-"` - QUICOptions V2RayQUICOptions `json:"-"` - GRPCOptions V2RayGRPCOptions `json:"-"` - HTTPUpgradeOptions V2RayHTTPUpgradeOptions `json:"-"` -} - -func (o *V2RayTransportOptions) MarshalJSON() ([]byte, error) { - switch o.Type { - case "ws": - return json.Marshal(&struct { - Type string `json:"type"` - *V2RayWebsocketOptions - }{ - Type: o.Type, - V2RayWebsocketOptions: &o.WebsocketOptions, - }) - case "quic": - return json.Marshal(&struct { - Type string `json:"type"` - *V2RayQUICOptions - }{ - Type: o.Type, - V2RayQUICOptions: &o.QUICOptions, - }) - case "grpc": - return json.Marshal(&struct { - Type string `json:"type"` - *V2RayGRPCOptions - }{ - Type: o.Type, - V2RayGRPCOptions: &o.GRPCOptions, - }) - case "http": - return json.Marshal(&struct { - Type string `json:"type"` - *V2RayHTTPOptions - }{ - Type: o.Type, - V2RayHTTPOptions: &o.HTTPOptions, - }) - default: - return json.Marshal(&struct{}{}) - } -} - -type V2RayHTTPOptions struct { - Host Listable[string] `json:"host,omitempty"` - Path string `json:"path,omitempty"` - Method string `json:"method,omitempty"` - Headers map[string]string `json:"headers,omitempty"` - IdleTimeout string `json:"idle_timeout,omitempty"` - PingTimeout string `json:"ping_timeout,omitempty"` -} - -type V2RayWebsocketOptions struct { - Path string `json:"path,omitempty"` - Headers map[string]string `json:"headers,omitempty"` - MaxEarlyData uint32 `json:"max_early_data,omitempty"` - EarlyDataHeaderName string `json:"early_data_header_name,omitempty"` -} - -type V2RayQUICOptions struct{} - -type V2RayGRPCOptions struct { - ServiceName string `json:"service_name,omitempty"` - IdleTimeout string `json:"idle_timeout,omitempty"` - PingTimeout string `json:"ping_timeout,omitempty"` - PermitWithoutStream bool `json:"permit_without_stream,omitempty"` - ForceLite bool `json:"-"` // for test -} - -type V2RayHTTPUpgradeOptions struct { - Host string `json:"host,omitempty"` - Path string `json:"path,omitempty"` - Headers map[string]string `json:"headers,omitempty"` -} diff --git a/model/vless.go b/model/vless.go deleted file mode 100644 index d656087..0000000 --- a/model/vless.go +++ /dev/null @@ -1,13 +0,0 @@ -package model - -type VLESSOutboundOptions struct { - DialerOptions - ServerOptions - UUID string `json:"uuid"` - Flow string `json:"flow,omitempty"` - Network string `json:"network,omitempty"` - OutboundTLSOptionsContainer - Multiplex *OutboundMultiplexOptions `json:"multiplex,omitempty"` - Transport *V2RayTransportOptions `json:"transport,omitempty"` - PacketEncoding *string `json:"packet_encoding,omitempty"` -} diff --git a/model/vmess.go b/model/vmess.go index a915b3b..0ee8cf2 100644 --- a/model/vmess.go +++ b/model/vmess.go @@ -17,18 +17,3 @@ type VmessJson struct { Alpn string `json:"alpn"` Fp string `json:"fp"` } - -type VMessOutboundOptions struct { - DialerOptions - ServerOptions - UUID string `json:"uuid"` - Security string `json:"security"` - AlterId int `json:"alter_id,omitempty"` - GlobalPadding bool `json:"global_padding,omitempty"` - AuthenticatedLength bool `json:"authenticated_length,omitempty"` - Network string `json:"network,omitempty"` - OutboundTLSOptionsContainer - PacketEncoding string `json:"packet_encoding,omitempty"` - Multiplex *OutboundMultiplexOptions `json:"multiplex,omitempty"` - Transport *V2RayTransportOptions `json:"transport,omitempty"` -} diff --git a/model/wireguard.go b/model/wireguard.go deleted file mode 100644 index 5d1dfd2..0000000 --- a/model/wireguard.go +++ /dev/null @@ -1,28 +0,0 @@ -package model - -import "net/netip" - -type WireGuardOutboundOptions struct { - DialerOptions - SystemInterface bool `json:"system_interface,omitempty"` - GSO bool `json:"gso,omitempty"` - InterfaceName string `json:"interface_name,omitempty"` - LocalAddress Listable[netip.Prefix] `json:"local_address"` - PrivateKey string `json:"private_key"` - Peers []WireGuardPeer `json:"peers,omitempty"` - ServerOptions - PeerPublicKey string `json:"peer_public_key"` - PreSharedKey string `json:"pre_shared_key,omitempty"` - Reserved []uint8 `json:"reserved,omitempty"` - Workers int `json:"workers,omitempty"` - MTU uint32 `json:"mtu,omitempty"` - Network string `json:"network,omitempty"` -} - -type WireGuardPeer struct { - ServerOptions - PublicKey string `json:"public_key,omitempty"` - PreSharedKey string `json:"pre_shared_key,omitempty"` - AllowedIPs Listable[string] `json:"allowed_ips,omitempty"` - Reserved []uint8 `json:"reserved,omitempty"` -} diff --git a/parser/hysteria.go b/parser/hysteria.go index bc5e87c..455d471 100644 --- a/parser/hysteria.go +++ b/parser/hysteria.go @@ -8,6 +8,7 @@ import ( "github.com/nitezs/sub2sing-box/constant" "github.com/nitezs/sub2sing-box/model" + "github.com/sagernet/sing-box/option" ) func ParseHysteria(proxy string) (model.Outbound, error) { @@ -70,11 +71,11 @@ func ParseHysteria(proxy string) (model.Outbound, error) { } remarks = strings.TrimSpace(remarks) - return model.Outbound{ + return model.Outbound{Outbound: option.Outbound{ Type: "hysteria", Tag: remarks, - HysteriaOptions: model.HysteriaOutboundOptions{ - ServerOptions: model.ServerOptions{ + HysteriaOptions: option.HysteriaOutboundOptions{ + ServerOptions: option.ServerOptions{ Server: server, ServerPort: port, }, @@ -82,14 +83,14 @@ func ParseHysteria(proxy string) (model.Outbound, error) { Down: downmbps, Auth: []byte(auth), Obfs: obfs, - Network: protocol, - OutboundTLSOptionsContainer: model.OutboundTLSOptionsContainer{ - TLS: &model.OutboundTLSOptions{ + Network: option.NetworkList(protocol), + OutboundTLSOptionsContainer: option.OutboundTLSOptionsContainer{ + TLS: &option.OutboundTLSOptions{ Enabled: true, Insecure: insecureBool, ALPN: alpn, }, }, }, - }, nil + }}, nil } diff --git a/parser/hysteria2.go b/parser/hysteria2.go index 328b929..ed2e1f5 100644 --- a/parser/hysteria2.go +++ b/parser/hysteria2.go @@ -7,6 +7,7 @@ import ( "github.com/nitezs/sub2sing-box/constant" "github.com/nitezs/sub2sing-box/model" + "github.com/sagernet/sing-box/option" ) func ParseHysteria2(proxy string) (model.Outbound, error) { @@ -64,29 +65,31 @@ func ParseHysteria2(proxy string) (model.Outbound, error) { remarks = strings.TrimSpace(remarks) result := model.Outbound{ - Type: "hysteria2", - Tag: strings.TrimSpace(remarks), - Hysteria2Options: model.Hysteria2OutboundOptions{ - ServerOptions: model.ServerOptions{ - Server: server, - ServerPort: port, - }, - Password: password, - OutboundTLSOptionsContainer: model.OutboundTLSOptionsContainer{ - TLS: &model.OutboundTLSOptions{ - Enabled: enableTLS, - Insecure: insecureBool, - ServerName: sni, + Outbound: option.Outbound{ + Type: "hysteria2", + Tag: strings.TrimSpace(remarks), + Hysteria2Options: option.Hysteria2OutboundOptions{ + ServerOptions: option.ServerOptions{ + Server: server, + ServerPort: port, }, + Password: password, + OutboundTLSOptionsContainer: option.OutboundTLSOptionsContainer{ + TLS: &option.OutboundTLSOptions{ + Enabled: enableTLS, + Insecure: insecureBool, + ServerName: sni, + }, + }, + Network: option.NetworkList(network), }, - Network: network, }, } if pinSHA256 != "" { result.Hysteria2Options.OutboundTLSOptionsContainer.TLS.Certificate = []string{pinSHA256} } if obfs != "" { - result.Hysteria2Options.Obfs = &model.Hysteria2Obfs{ + result.Hysteria2Options.Obfs = &option.Hysteria2Obfs{ Type: obfs, Password: obfsPassword, } diff --git a/parser/shadowsocks.go b/parser/shadowsocks.go index ef5dc8f..a4f356f 100644 --- a/parser/shadowsocks.go +++ b/parser/shadowsocks.go @@ -8,6 +8,7 @@ import ( "github.com/nitezs/sub2sing-box/constant" "github.com/nitezs/sub2sing-box/model" "github.com/nitezs/sub2sing-box/util" + "github.com/sagernet/sing-box/option" ) func ParseShadowsocks(proxy string) (model.Outbound, error) { @@ -95,17 +96,19 @@ func ParseShadowsocks(proxy string) (model.Outbound, error) { remarks = strings.TrimSpace(remarks) result := model.Outbound{ - Type: "shadowsocks", - Tag: remarks, - ShadowsocksOptions: model.ShadowsocksOutboundOptions{ - ServerOptions: model.ServerOptions{ - Server: server, - ServerPort: port, + Outbound: option.Outbound{ + Type: "shadowsocks", + Tag: remarks, + ShadowsocksOptions: option.ShadowsocksOutboundOptions{ + ServerOptions: option.ServerOptions{ + Server: server, + ServerPort: port, + }, + Method: method, + Password: password, + Plugin: plugin, + PluginOptions: options, }, - Method: method, - Password: password, - Plugin: plugin, - PluginOptions: options, }, } return result, nil diff --git a/parser/trojan.go b/parser/trojan.go index 5d89a58..91cde95 100644 --- a/parser/trojan.go +++ b/parser/trojan.go @@ -7,6 +7,7 @@ import ( "github.com/nitezs/sub2sing-box/constant" "github.com/nitezs/sub2sing-box/model" + "github.com/sagernet/sing-box/option" ) func ParseTrojan(proxy string) (model.Outbound, error) { @@ -68,22 +69,22 @@ func ParseTrojan(proxy string) (model.Outbound, error) { enableUTLS := fp != "" - result := model.Outbound{ + result := model.Outbound{Outbound: option.Outbound{ Type: "trojan", Tag: remarks, - TrojanOptions: model.TrojanOutboundOptions{ - ServerOptions: model.ServerOptions{ + TrojanOptions: option.TrojanOutboundOptions{ + ServerOptions: option.ServerOptions{ Server: server, ServerPort: port, }, Password: password, - Network: network, + Network: option.NetworkList(network), }, - } + }} if security == "xtls" || security == "tls" || sni != "" { - result.TrojanOptions.OutboundTLSOptionsContainer = model.OutboundTLSOptionsContainer{ - TLS: &model.OutboundTLSOptions{ + result.TrojanOptions.OutboundTLSOptionsContainer = option.OutboundTLSOptionsContainer{ + TLS: &option.OutboundTLSOptions{ Enabled: true, ALPN: alpn, ServerName: sni, @@ -93,16 +94,16 @@ func ParseTrojan(proxy string) (model.Outbound, error) { } if security == "reality" { - result.TrojanOptions.OutboundTLSOptionsContainer = model.OutboundTLSOptionsContainer{ - TLS: &model.OutboundTLSOptions{ + result.TrojanOptions.OutboundTLSOptionsContainer = option.OutboundTLSOptionsContainer{ + TLS: &option.OutboundTLSOptions{ Enabled: true, ServerName: sni, - Reality: &model.OutboundRealityOptions{ + Reality: &option.OutboundRealityOptions{ Enabled: true, PublicKey: pbk, ShortID: sid, }, - UTLS: &model.OutboundUTLSOptions{ + UTLS: &option.OutboundUTLSOptions{ Enabled: enableUTLS, Fingerprint: fp, }, @@ -112,21 +113,21 @@ func ParseTrojan(proxy string) (model.Outbound, error) { } if network == "ws" { - result.TrojanOptions.Transport = &model.V2RayTransportOptions{ + result.TrojanOptions.Transport = &option.V2RayTransportOptions{ Type: "ws", - WebsocketOptions: model.V2RayWebsocketOptions{ + WebsocketOptions: option.V2RayWebsocketOptions{ Path: path, - Headers: map[string]string{ - "Host": host, + Headers: map[string]option.Listable[string]{ + "Host": {host}, }, }, } } if network == "http" { - result.TrojanOptions.Transport = &model.V2RayTransportOptions{ + result.TrojanOptions.Transport = &option.V2RayTransportOptions{ Type: "http", - HTTPOptions: model.V2RayHTTPOptions{ + HTTPOptions: option.V2RayHTTPOptions{ Host: []string{host}, Path: path, }, @@ -134,16 +135,16 @@ func ParseTrojan(proxy string) (model.Outbound, error) { } if network == "quic" { - result.TrojanOptions.Transport = &model.V2RayTransportOptions{ + result.TrojanOptions.Transport = &option.V2RayTransportOptions{ Type: "quic", - QUICOptions: model.V2RayQUICOptions{}, + QUICOptions: option.V2RayQUICOptions{}, } } if network == "grpc" { - result.TrojanOptions.Transport = &model.V2RayTransportOptions{ + result.TrojanOptions.Transport = &option.V2RayTransportOptions{ Type: "grpc", - GRPCOptions: model.V2RayGRPCOptions{ + GRPCOptions: option.V2RayGRPCOptions{ ServiceName: serviceName, }, } diff --git a/parser/vless.go b/parser/vless.go index d9c9ce9..f7ab8c0 100644 --- a/parser/vless.go +++ b/parser/vless.go @@ -7,6 +7,7 @@ import ( "github.com/nitezs/sub2sing-box/constant" "github.com/nitezs/sub2sing-box/model" + "github.com/sagernet/sing-box/option" ) func ParseVless(proxy string) (model.Outbound, error) { @@ -59,22 +60,22 @@ func ParseVless(proxy string) (model.Outbound, error) { } remarks = strings.TrimSpace(remarks) - result := model.Outbound{ + result := model.Outbound{Outbound: option.Outbound{ Type: "vless", Tag: remarks, - VLESSOptions: model.VLESSOutboundOptions{ - ServerOptions: model.ServerOptions{ + VLESSOptions: option.VLESSOutboundOptions{ + ServerOptions: option.ServerOptions{ Server: server, ServerPort: port, }, UUID: uuid, Flow: flow, }, - } + }} if security == "tls" { - result.VLESSOptions.OutboundTLSOptionsContainer = model.OutboundTLSOptionsContainer{ - TLS: &model.OutboundTLSOptions{ + result.VLESSOptions.OutboundTLSOptionsContainer = option.OutboundTLSOptionsContainer{ + TLS: &option.OutboundTLSOptions{ Enabled: true, ALPN: alpn, ServerName: sni, @@ -84,13 +85,13 @@ func ParseVless(proxy string) (model.Outbound, error) { } if security == "reality" { - result.VLESSOptions.OutboundTLSOptionsContainer = model.OutboundTLSOptionsContainer{ - TLS: &model.OutboundTLSOptions{ + result.VLESSOptions.OutboundTLSOptionsContainer = option.OutboundTLSOptionsContainer{ + TLS: &option.OutboundTLSOptions{ Enabled: true, ALPN: alpn, ServerName: sni, Insecure: insecureBool, - Reality: &model.OutboundRealityOptions{ + Reality: &option.OutboundRealityOptions{ Enabled: true, PublicKey: pbk, ShortID: sid, @@ -100,31 +101,31 @@ func ParseVless(proxy string) (model.Outbound, error) { } if _type == "ws" { - result.VLESSOptions.Transport = &model.V2RayTransportOptions{ + result.VLESSOptions.Transport = &option.V2RayTransportOptions{ Type: "ws", - WebsocketOptions: model.V2RayWebsocketOptions{ + WebsocketOptions: option.V2RayWebsocketOptions{ Path: path, }, } if host != "" { if result.VLESSOptions.Transport.WebsocketOptions.Headers == nil { - result.VLESSOptions.Transport.WebsocketOptions.Headers = make(map[string]string) + result.VLESSOptions.Transport.WebsocketOptions.Headers = make(map[string]option.Listable[string]) } - result.VLESSOptions.Transport.WebsocketOptions.Headers["Host"] = host + result.VLESSOptions.Transport.WebsocketOptions.Headers["Host"] = option.Listable[string]{host} } } if _type == "quic" { - result.VLESSOptions.Transport = &model.V2RayTransportOptions{ + result.VLESSOptions.Transport = &option.V2RayTransportOptions{ Type: "quic", - QUICOptions: model.V2RayQUICOptions{}, + QUICOptions: option.V2RayQUICOptions{}, } } if _type == "grpc" { - result.VLESSOptions.Transport = &model.V2RayTransportOptions{ + result.VLESSOptions.Transport = &option.V2RayTransportOptions{ Type: "grpc", - GRPCOptions: model.V2RayGRPCOptions{ + GRPCOptions: option.V2RayGRPCOptions{ ServiceName: serviceName, }, } @@ -139,16 +140,16 @@ func ParseVless(proxy string) (model.Outbound, error) { Message: err.Error(), } } - result.VLESSOptions.Transport = &model.V2RayTransportOptions{ + result.VLESSOptions.Transport = &option.V2RayTransportOptions{ Type: "http", - HTTPOptions: model.V2RayHTTPOptions{ + HTTPOptions: option.V2RayHTTPOptions{ Host: strings.Split(hosts, ","), }, } } if enableUTLS { - result.VLESSOptions.OutboundTLSOptionsContainer.TLS.UTLS = &model.OutboundUTLSOptions{ + result.VLESSOptions.OutboundTLSOptionsContainer.TLS.UTLS = &option.OutboundUTLSOptions{ Enabled: enableUTLS, Fingerprint: fp, } diff --git a/parser/vmess.go b/parser/vmess.go index 3fa66bb..1d6c165 100644 --- a/parser/vmess.go +++ b/parser/vmess.go @@ -9,6 +9,7 @@ import ( "github.com/nitezs/sub2sing-box/constant" "github.com/nitezs/sub2sing-box/model" "github.com/nitezs/sub2sing-box/util" + "github.com/sagernet/sing-box/option" ) func ParseVmess(proxy string) (model.Outbound, error) { @@ -64,16 +65,18 @@ func ParseVmess(proxy string) (model.Outbound, error) { } result := model.Outbound{ - Type: "vmess", - Tag: name, - VMessOptions: model.VMessOutboundOptions{ - ServerOptions: model.ServerOptions{ - Server: vmess.Add, - ServerPort: port, + Outbound: option.Outbound{ + Type: "vmess", + Tag: name, + VMessOptions: option.VMessOutboundOptions{ + ServerOptions: option.ServerOptions{ + Server: vmess.Add, + ServerPort: port, + }, + UUID: vmess.Id, + AlterId: aid, + Security: vmess.Scy, }, - UUID: vmess.Id, - AlterId: aid, - Security: vmess.Scy, }, } @@ -84,10 +87,10 @@ func ParseVmess(proxy string) (model.Outbound, error) { } else { alpn = nil } - result.VMessOptions.OutboundTLSOptionsContainer = model.OutboundTLSOptionsContainer{ - TLS: &model.OutboundTLSOptions{ + result.VMessOptions.OutboundTLSOptionsContainer = option.OutboundTLSOptionsContainer{ + TLS: &option.OutboundTLSOptions{ Enabled: true, - UTLS: &model.OutboundUTLSOptions{ + UTLS: &option.OutboundUTLSOptions{ Fingerprint: vmess.Fp, }, ALPN: alpn, @@ -95,7 +98,7 @@ func ParseVmess(proxy string) (model.Outbound, error) { }, } if vmess.Fp != "" { - result.VMessOptions.OutboundTLSOptionsContainer.TLS.UTLS = &model.OutboundUTLSOptions{ + result.VMessOptions.OutboundTLSOptionsContainer.TLS.UTLS = &option.OutboundUTLSOptions{ Enabled: true, Fingerprint: vmess.Fp, } @@ -109,42 +112,42 @@ func ParseVmess(proxy string) (model.Outbound, error) { if vmess.Host == "" { vmess.Host = vmess.Add } - result.VMessOptions.Transport = &model.V2RayTransportOptions{ + result.VMessOptions.Transport = &option.V2RayTransportOptions{ Type: "ws", - WebsocketOptions: model.V2RayWebsocketOptions{ + WebsocketOptions: option.V2RayWebsocketOptions{ Path: vmess.Path, - Headers: map[string]string{ - "Host": vmess.Host, + Headers: map[string]option.Listable[string]{ + "Host": {vmess.Host}, }, }, } } if vmess.Net == "quic" { - quic := model.V2RayQUICOptions{} - result.VMessOptions.Transport = &model.V2RayTransportOptions{ + quic := option.V2RayQUICOptions{} + result.VMessOptions.Transport = &option.V2RayTransportOptions{ Type: "quic", QUICOptions: quic, } } if vmess.Net == "grpc" { - grpc := model.V2RayGRPCOptions{ + grpc := option.V2RayGRPCOptions{ ServiceName: vmess.Path, PermitWithoutStream: true, } - result.VMessOptions.Transport = &model.V2RayTransportOptions{ + result.VMessOptions.Transport = &option.V2RayTransportOptions{ Type: "grpc", GRPCOptions: grpc, } } if vmess.Net == "h2" { - httpOps := model.V2RayHTTPOptions{ + httpOps := option.V2RayHTTPOptions{ Host: strings.Split(vmess.Host, ","), Path: vmess.Path, } - result.VMessOptions.Transport = &model.V2RayTransportOptions{ + result.VMessOptions.Transport = &option.V2RayTransportOptions{ Type: "http", HTTPOptions: httpOps, } diff --git a/templates/example.json b/templates/example.json index d5a67ab..42378eb 100644 --- a/templates/example.json +++ b/templates/example.json @@ -78,7 +78,6 @@ ], "outbounds": [ { - "interrupt_exist_connections": true, "outbounds": ["", "direct"], "tag": "default", "type": "selector"