mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-26 02:21:28 +00:00
Add format config support
This commit is contained in:
parent
30444057bd
commit
85a695caa1
|
@ -21,6 +21,7 @@ func init() {
|
||||||
var (
|
var (
|
||||||
configPath string
|
configPath string
|
||||||
workingDir string
|
workingDir string
|
||||||
|
formatConfig bool
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -30,6 +31,7 @@ func main() {
|
||||||
}
|
}
|
||||||
command.Flags().StringVarP(&configPath, "config", "c", "config.json", "set configuration file path")
|
command.Flags().StringVarP(&configPath, "config", "c", "config.json", "set configuration file path")
|
||||||
command.Flags().StringVarP(&workingDir, "directory", "D", "", "set working directory")
|
command.Flags().StringVarP(&workingDir, "directory", "D", "", "set working directory")
|
||||||
|
command.Flags().BoolVarP(&formatConfig, "format", "f", false, "print formatted configuration file")
|
||||||
if err := command.Execute(); err != nil {
|
if err := command.Execute(); err != nil {
|
||||||
logrus.Fatal(err)
|
logrus.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -57,6 +59,18 @@ func run(cmd *cobra.Command, args []string) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Fatal("create service: ", err)
|
logrus.Fatal("create service: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if formatConfig {
|
||||||
|
cancel()
|
||||||
|
encoder := json.NewEncoder(os.Stdout)
|
||||||
|
encoder.SetIndent("", " ")
|
||||||
|
err = encoder.Encode(options)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatal("encode config: ", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
err = service.Start()
|
err = service.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Fatal("start service: ", err)
|
logrus.Fatal("start service: ", err)
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -6,7 +6,7 @@ require (
|
||||||
github.com/database64128/tfo-go v1.0.4
|
github.com/database64128/tfo-go v1.0.4
|
||||||
github.com/logrusorgru/aurora v2.0.3+incompatible
|
github.com/logrusorgru/aurora v2.0.3+incompatible
|
||||||
github.com/oschwald/geoip2-golang v1.7.0
|
github.com/oschwald/geoip2-golang v1.7.0
|
||||||
github.com/sagernet/sing v0.0.0-20220702174608-cb5bb5132de4
|
github.com/sagernet/sing v0.0.0-20220702193452-6a6c180cf77e
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220701084835-2208da1d8649
|
github.com/sagernet/sing-shadowsocks v0.0.0-20220701084835-2208da1d8649
|
||||||
github.com/sirupsen/logrus v1.8.1
|
github.com/sirupsen/logrus v1.8.1
|
||||||
github.com/spf13/cobra v1.5.0
|
github.com/spf13/cobra v1.5.0
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -18,8 +18,8 @@ github.com/oschwald/maxminddb-golang v1.9.0/go.mod h1:TK+s/Z2oZq0rSl4PSeAEoP0bgm
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/sagernet/sing v0.0.0-20220702174608-cb5bb5132de4 h1:Ce6nW9gV6g2hq/1K/nMtlVGiTtxh86EWs0/jOzMuNa4=
|
github.com/sagernet/sing v0.0.0-20220702193452-6a6c180cf77e h1:GiH/gZcH8fupEfWJujaqGNBBaCkAouAJyVJy9Afxfvw=
|
||||||
github.com/sagernet/sing v0.0.0-20220702174608-cb5bb5132de4/go.mod h1:3ZmoGNg/nNJTyHAZFNRSPaXpNIwpDvyIiAUd0KIWV5c=
|
github.com/sagernet/sing v0.0.0-20220702193452-6a6c180cf77e/go.mod h1:3ZmoGNg/nNJTyHAZFNRSPaXpNIwpDvyIiAUd0KIWV5c=
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220701084835-2208da1d8649 h1:whNDUGOAX5GPZkSy4G3Gv9QyIgk5SXRyjkRuP7ohF8k=
|
github.com/sagernet/sing-shadowsocks v0.0.0-20220701084835-2208da1d8649 h1:whNDUGOAX5GPZkSy4G3Gv9QyIgk5SXRyjkRuP7ohF8k=
|
||||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220701084835-2208da1d8649/go.mod h1:MuyT+9fEPjvauAv0fSE0a6Q+l0Tv2ZrAafTkYfnxBFw=
|
github.com/sagernet/sing-shadowsocks v0.0.0-20220701084835-2208da1d8649/go.mod h1:MuyT+9fEPjvauAv0fSE0a6Q+l0Tv2ZrAafTkYfnxBFw=
|
||||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||||
|
|
|
@ -7,9 +7,12 @@ import (
|
||||||
|
|
||||||
type ListenAddress netip.Addr
|
type ListenAddress netip.Addr
|
||||||
|
|
||||||
func (a *ListenAddress) MarshalJSON() ([]byte, error) {
|
func (a ListenAddress) MarshalJSON() ([]byte, error) {
|
||||||
value := netip.Addr(*a).String()
|
addr := netip.Addr(a)
|
||||||
return json.Marshal(value)
|
if !addr.IsValid() {
|
||||||
|
return json.Marshal("")
|
||||||
|
}
|
||||||
|
return json.Marshal(addr.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ListenAddress) UnmarshalJSON(bytes []byte) error {
|
func (a *ListenAddress) UnmarshalJSON(bytes []byte) error {
|
||||||
|
|
|
@ -3,7 +3,7 @@ package option
|
||||||
import "github.com/sagernet/sing/common"
|
import "github.com/sagernet/sing/common"
|
||||||
|
|
||||||
type Options struct {
|
type Options struct {
|
||||||
Log *LogOption `json:"log"`
|
Log *LogOption `json:"log,omitempty"`
|
||||||
Inbounds []Inbound `json:"inbounds,omitempty"`
|
Inbounds []Inbound `json:"inbounds,omitempty"`
|
||||||
Outbounds []Outbound `json:"outbounds,omitempty"`
|
Outbounds []Outbound `json:"outbounds,omitempty"`
|
||||||
Route *RouteOptions `json:"route,omitempty"`
|
Route *RouteOptions `json:"route,omitempty"`
|
||||||
|
|
|
@ -20,52 +20,52 @@ type _Inbound struct {
|
||||||
|
|
||||||
type Inbound _Inbound
|
type Inbound _Inbound
|
||||||
|
|
||||||
func (i Inbound) Equals(other Inbound) bool {
|
func (h Inbound) Equals(other Inbound) bool {
|
||||||
return i.Type == other.Type &&
|
return h.Type == other.Type &&
|
||||||
i.Tag == other.Tag &&
|
h.Tag == other.Tag &&
|
||||||
common.Equals(i.DirectOptions, other.DirectOptions) &&
|
common.Equals(h.DirectOptions, other.DirectOptions) &&
|
||||||
common.Equals(i.SocksOptions, other.SocksOptions) &&
|
common.Equals(h.SocksOptions, other.SocksOptions) &&
|
||||||
common.Equals(i.HTTPOptions, other.HTTPOptions) &&
|
common.Equals(h.HTTPOptions, other.HTTPOptions) &&
|
||||||
common.Equals(i.MixedOptions, other.MixedOptions) &&
|
common.Equals(h.MixedOptions, other.MixedOptions) &&
|
||||||
common.Equals(i.ShadowsocksOptions, other.ShadowsocksOptions)
|
common.Equals(h.ShadowsocksOptions, other.ShadowsocksOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Inbound) MarshalJSON() ([]byte, error) {
|
func (h Inbound) MarshalJSON() ([]byte, error) {
|
||||||
var v any
|
var v any
|
||||||
switch i.Type {
|
switch h.Type {
|
||||||
case "direct":
|
case "direct":
|
||||||
v = i.DirectOptions
|
v = h.DirectOptions
|
||||||
case "socks":
|
case "socks":
|
||||||
v = i.SocksOptions
|
v = h.SocksOptions
|
||||||
case "http":
|
case "http":
|
||||||
v = i.HTTPOptions
|
v = h.HTTPOptions
|
||||||
case "mixed":
|
case "mixed":
|
||||||
v = i.MixedOptions
|
v = h.MixedOptions
|
||||||
case "shadowsocks":
|
case "shadowsocks":
|
||||||
v = i.ShadowsocksOptions
|
v = h.ShadowsocksOptions
|
||||||
default:
|
default:
|
||||||
return nil, E.New("unknown inbound type: ", i.Type)
|
return nil, E.New("unknown inbound type: ", h.Type)
|
||||||
}
|
}
|
||||||
return MarshallObjects(i, v)
|
return MarshallObjects((_Inbound)(h), v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Inbound) UnmarshalJSON(bytes []byte) error {
|
func (h *Inbound) UnmarshalJSON(bytes []byte) error {
|
||||||
err := json.Unmarshal(bytes, (*_Inbound)(i))
|
err := json.Unmarshal(bytes, (*_Inbound)(h))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var v any
|
var v any
|
||||||
switch i.Type {
|
switch h.Type {
|
||||||
case "direct":
|
case "direct":
|
||||||
v = &i.DirectOptions
|
v = &h.DirectOptions
|
||||||
case "socks":
|
case "socks":
|
||||||
v = &i.SocksOptions
|
v = &h.SocksOptions
|
||||||
case "http":
|
case "http":
|
||||||
v = &i.HTTPOptions
|
v = &h.HTTPOptions
|
||||||
case "mixed":
|
case "mixed":
|
||||||
v = &i.MixedOptions
|
v = &h.MixedOptions
|
||||||
case "shadowsocks":
|
case "shadowsocks":
|
||||||
v = &i.ShadowsocksOptions
|
v = &h.ShadowsocksOptions
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,33 +2,33 @@ package option
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing/common/x/linkedhashmap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ToMap(v any) (map[string]any, error) {
|
func ToMap(v any) (*linkedhashmap.Map[string, any], error) {
|
||||||
bytes, err := json.Marshal(v)
|
bytes, err := json.Marshal(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var content map[string]any
|
var content linkedhashmap.Map[string, any]
|
||||||
err = json.Unmarshal(bytes, &content)
|
err = json.Unmarshal(bytes, &content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return content, nil
|
return &content, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func MergeObjects(objects ...any) (map[string]any, error) {
|
func MergeObjects(objects ...any) (*linkedhashmap.Map[string, any], error) {
|
||||||
content := make(map[string]any)
|
var content linkedhashmap.Map[string, any]
|
||||||
for _, object := range objects {
|
for _, object := range objects {
|
||||||
objectMap, err := ToMap(object)
|
objectMap, err := ToMap(object)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for k, v := range objectMap {
|
content.PutAll(objectMap)
|
||||||
content[k] = v
|
|
||||||
}
|
}
|
||||||
}
|
return &content, nil
|
||||||
return content, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func MarshallObjects(objects ...any) ([]byte, error) {
|
func MarshallObjects(objects ...any) ([]byte, error) {
|
||||||
|
|
|
@ -4,8 +4,8 @@ import "encoding/json"
|
||||||
|
|
||||||
type Listable[T comparable] []T
|
type Listable[T comparable] []T
|
||||||
|
|
||||||
func (l *Listable[T]) MarshalJSON() ([]byte, error) {
|
func (l Listable[T]) MarshalJSON() ([]byte, error) {
|
||||||
arrayList := []T(*l)
|
arrayList := []T(l)
|
||||||
if len(arrayList) == 1 {
|
if len(arrayList) == 1 {
|
||||||
return json.Marshal(arrayList[0])
|
return json.Marshal(arrayList[0])
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,30 +16,30 @@ type _Outbound struct {
|
||||||
|
|
||||||
type Outbound _Outbound
|
type Outbound _Outbound
|
||||||
|
|
||||||
func (i *Outbound) MarshalJSON() ([]byte, error) {
|
func (h Outbound) MarshalJSON() ([]byte, error) {
|
||||||
var v any
|
var v any
|
||||||
switch i.Type {
|
switch h.Type {
|
||||||
case "direct":
|
case "direct":
|
||||||
v = i.DirectOptions
|
v = h.DirectOptions
|
||||||
case "shadowsocks":
|
case "shadowsocks":
|
||||||
v = i.ShadowsocksOptions
|
v = h.ShadowsocksOptions
|
||||||
default:
|
default:
|
||||||
return nil, E.New("unknown outbound type: ", i.Type)
|
return nil, E.New("unknown outbound type: ", h.Type)
|
||||||
}
|
}
|
||||||
return MarshallObjects(i, v)
|
return MarshallObjects((_Outbound)(h), v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Outbound) UnmarshalJSON(bytes []byte) error {
|
func (h *Outbound) UnmarshalJSON(bytes []byte) error {
|
||||||
err := json.Unmarshal(bytes, (*_Outbound)(i))
|
err := json.Unmarshal(bytes, (*_Outbound)(h))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var v any
|
var v any
|
||||||
switch i.Type {
|
switch h.Type {
|
||||||
case "direct":
|
case "direct":
|
||||||
v = &i.DirectOptions
|
v = &h.DirectOptions
|
||||||
case "shadowsocks":
|
case "shadowsocks":
|
||||||
v = &i.ShadowsocksOptions
|
v = &h.ShadowsocksOptions
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,8 @@ type GeoIPOptions struct {
|
||||||
|
|
||||||
type _Rule struct {
|
type _Rule struct {
|
||||||
Type string `json:"type,omitempty"`
|
Type string `json:"type,omitempty"`
|
||||||
DefaultOptions *DefaultRule `json:"default_options,omitempty"`
|
DefaultOptions *DefaultRule `json:"-"`
|
||||||
LogicalOptions *LogicalRule `json:"logical_options,omitempty"`
|
LogicalOptions *LogicalRule `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Rule _Rule
|
type Rule _Rule
|
||||||
|
@ -38,7 +38,7 @@ func (r Rule) Equals(other Rule) bool {
|
||||||
common.PtrEquals(r.LogicalOptions, other.LogicalOptions)
|
common.PtrEquals(r.LogicalOptions, other.LogicalOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Rule) MarshalJSON() ([]byte, error) {
|
func (r Rule) MarshalJSON() ([]byte, error) {
|
||||||
var v any
|
var v any
|
||||||
switch r.Type {
|
switch r.Type {
|
||||||
case C.RuleTypeDefault:
|
case C.RuleTypeDefault:
|
||||||
|
@ -48,7 +48,7 @@ func (r *Rule) MarshalJSON() ([]byte, error) {
|
||||||
default:
|
default:
|
||||||
return nil, E.New("unknown rule type: " + r.Type)
|
return nil, E.New("unknown rule type: " + r.Type)
|
||||||
}
|
}
|
||||||
return MarshallObjects(r, v)
|
return MarshallObjects((_Rule)(r), v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Rule) UnmarshalJSON(bytes []byte) error {
|
func (r *Rule) UnmarshalJSON(bytes []byte) error {
|
||||||
|
|
Loading…
Reference in a new issue