From 1e76123a4c3ad12e004363aaba2c57638516ce82 Mon Sep 17 00:00:00 2001 From: vcptr <51714622+vcptr@users.noreply.github.com> Date: Sat, 14 Dec 2019 22:24:32 +0800 Subject: [PATCH] main loads multiple --- common/platform/ctlcmd/ctlcmd.go | 4 +- infra/control/{mconfig.go => config.go} | 2 +- main/confloader/confloader.go | 19 ----- main/confloader/external/external.go | 48 ----------- main/distro/all/all.go | 3 - main/json/config_json.go | 7 +- .../external => jsonem}/errors.generated.go | 2 +- main/jsonem/jsonem.go | 80 ++++++++++++++++++- main/main.go | 49 +++++++----- 9 files changed, 118 insertions(+), 96 deletions(-) rename infra/control/{mconfig.go => config.go} (98%) delete mode 100644 main/confloader/confloader.go delete mode 100644 main/confloader/external/external.go rename main/{confloader/external => jsonem}/errors.generated.go (91%) diff --git a/common/platform/ctlcmd/ctlcmd.go b/common/platform/ctlcmd/ctlcmd.go index 91c22e50..adebbf7a 100644 --- a/common/platform/ctlcmd/ctlcmd.go +++ b/common/platform/ctlcmd/ctlcmd.go @@ -39,8 +39,10 @@ func Run(args []string, input io.Reader) (buf.MultiBuffer, error) { } return nil, newError(msg).Base(err) } + + // log stderr, info message if !errBuffer.IsEmpty() { - newError("v2ctl > ", errBuffer.String()).AtInfo().WriteToLog() + newError("v2ctl > \n", errBuffer.MultiBuffer.String()).AtInfo().WriteToLog() } return outBuffer.MultiBuffer, nil diff --git a/infra/control/mconfig.go b/infra/control/config.go similarity index 98% rename from infra/control/mconfig.go rename to infra/control/config.go index 5222df41..aa6d142a 100644 --- a/infra/control/mconfig.go +++ b/infra/control/config.go @@ -16,7 +16,7 @@ import ( type MconfigCommand struct{} func (c *MconfigCommand) Name() string { - return "mconfig" + return "config" } func (c *MconfigCommand) Description() Description { diff --git a/main/confloader/confloader.go b/main/confloader/confloader.go deleted file mode 100644 index 9edf6909..00000000 --- a/main/confloader/confloader.go +++ /dev/null @@ -1,19 +0,0 @@ -package confloader - -import ( - "io" - "os" -) - -type configFileLoader func(string) (io.ReadCloser, error) - -var ( - EffectiveConfigFileLoader configFileLoader -) - -func LoadConfig(file string) (io.ReadCloser, error) { - if EffectiveConfigFileLoader == nil { - return os.Stdin, nil - } - return EffectiveConfigFileLoader(file) -} diff --git a/main/confloader/external/external.go b/main/confloader/external/external.go deleted file mode 100644 index 75dcdea3..00000000 --- a/main/confloader/external/external.go +++ /dev/null @@ -1,48 +0,0 @@ -package external - -import ( - "io" - "os" - "strings" - - "v2ray.com/core/common/buf" - "v2ray.com/core/common/platform/ctlcmd" - "v2ray.com/core/main/confloader" -) - -//go:generate errorgen - -func loadConfigFile(configFile string) (io.ReadCloser, error) { - if configFile == "stdin:" { - return os.Stdin, nil - } - - if strings.HasPrefix(configFile, "http://") || strings.HasPrefix(configFile, "https://") { - content, err := ctlcmd.Run([]string{"fetch", configFile}, nil) - if err != nil { - return nil, err - } - return &buf.MultiBufferContainer{ - MultiBuffer: content, - }, nil - } - - fixedFile := os.ExpandEnv(configFile) - file, err := os.Open(fixedFile) - if err != nil { - return nil, newError("config file not readable").Base(err) - } - defer file.Close() - - content, err := buf.ReadFrom(file) - if err != nil { - return nil, newError("failed to load config file: ", fixedFile).Base(err).AtWarning() - } - return &buf.MultiBufferContainer{ - MultiBuffer: content, - }, nil -} - -func init() { - confloader.EffectiveConfigFileLoader = loadConfigFile -} diff --git a/main/distro/all/all.go b/main/distro/all/all.go index 71144c08..f7986889 100644 --- a/main/distro/all/all.go +++ b/main/distro/all/all.go @@ -58,7 +58,4 @@ import ( _ "v2ray.com/core/main/json" // The following line loads JSON internally // _ "v2ray.com/core/main/jsonem" - - // Load config from file or http(s) - _ "v2ray.com/core/main/confloader/external" ) diff --git a/main/json/config_json.go b/main/json/config_json.go index 45c6374d..274f0aac 100644 --- a/main/json/config_json.go +++ b/main/json/config_json.go @@ -3,7 +3,9 @@ package json //go:generate errorgen import ( + "encoding/json" "io" + "io/ioutil" "v2ray.com/core" "v2ray.com/core/common" @@ -16,7 +18,10 @@ func init() { Name: "JSON", Extension: []string{"json"}, Loader: func(input io.Reader) (*core.Config, error) { - jsonContent, err := ctlcmd.Run([]string{"config"}, input) + fns := []string{} + data, _ := ioutil.ReadAll(input) + json.Unmarshal(data, &fns) + jsonContent, err := ctlcmd.Run(append([]string{"config"}, fns...), nil) if err != nil { return nil, newError("failed to execute v2ctl to convert config file.").Base(err).AtWarning() } diff --git a/main/confloader/external/errors.generated.go b/main/jsonem/errors.generated.go similarity index 91% rename from main/confloader/external/errors.generated.go rename to main/jsonem/errors.generated.go index 919f10d0..48961bce 100644 --- a/main/confloader/external/errors.generated.go +++ b/main/jsonem/errors.generated.go @@ -1,4 +1,4 @@ -package external +package jsonem import "v2ray.com/core/common/errors" diff --git a/main/jsonem/jsonem.go b/main/jsonem/jsonem.go index 7b58bb9b..d8bf1f7b 100644 --- a/main/jsonem/jsonem.go +++ b/main/jsonem/jsonem.go @@ -1,8 +1,19 @@ package jsonem import ( + "bytes" + "encoding/json" + "io" + "io/ioutil" + "net/http" + "net/url" + "strings" + "time" + "v2ray.com/core" "v2ray.com/core/common" + "v2ray.com/core/common/buf" + "v2ray.com/core/infra/conf" "v2ray.com/core/infra/conf/serial" ) @@ -10,6 +21,71 @@ func init() { common.Must(core.RegisterConfigLoader(&core.ConfigFormat{ Name: "JSON", Extension: []string{"json"}, - Loader: serial.LoadJSONConfig, - })) + Loader: func(input io.Reader) (*core.Config, error) { + fns := []string{} + data, _ := ioutil.ReadAll(input) + json.Unmarshal(data, &fns) + + cf := &conf.Config{} + for _, arg := range fns { + r, err := LoadArg(arg) + common.Must(err) + c, err := serial.DecodeJSONConfig(r) + common.Must(err) + cf.Override(c, arg) + } + return cf.Build() + }})) +} + +func LoadArg(arg string) (out io.Reader, err error) { + + var data []byte + if strings.HasPrefix(arg, "http://") || strings.HasPrefix(arg, "https://") { + data, err = FetchHTTPContent(arg) + } else { + data, err = ioutil.ReadFile(arg) + } + + if err != nil { + return + } + out = bytes.NewBuffer(data) + return +} + +func FetchHTTPContent(target string) ([]byte, error) { + + parsedTarget, err := url.Parse(target) + if err != nil { + return nil, newError("invalid URL: ", target).Base(err) + } + + if s := strings.ToLower(parsedTarget.Scheme); s != "http" && s != "https" { + return nil, newError("invalid scheme: ", parsedTarget.Scheme) + } + + client := &http.Client{ + Timeout: 30 * time.Second, + } + resp, err := client.Do(&http.Request{ + Method: "GET", + URL: parsedTarget, + Close: true, + }) + if err != nil { + return nil, newError("failed to dial to ", target).Base(err) + } + defer resp.Body.Close() + + if resp.StatusCode != 200 { + return nil, newError("unexpected HTTP status code: ", resp.StatusCode) + } + + content, err := buf.ReadAllToBytes(resp.Body) + if err != nil { + return nil, newError("failed to read HTTP response").Base(err) + } + + return content, nil } diff --git a/main/main.go b/main/main.go index a5d3a447..1b8adca2 100644 --- a/main/main.go +++ b/main/main.go @@ -3,6 +3,8 @@ package main //go:generate errorgen import ( + "bytes" + "encoding/json" "flag" "fmt" "os" @@ -14,15 +16,25 @@ import ( "v2ray.com/core" "v2ray.com/core/common/platform" - "v2ray.com/core/main/confloader" _ "v2ray.com/core/main/distro/all" ) +type CmdConfig []string + +func (c *CmdConfig) String() string { + return strings.Join([]string(*c), ",") +} + +func (c *CmdConfig) Set(value string) error { + *c = append(*c, value) + return nil +} + var ( - configFile = flag.String("config", "", "Config file for V2Ray.") - version = flag.Bool("version", false, "Show current version of V2Ray.") - test = flag.Bool("test", false, "Test config file only, without launching V2Ray server.") - format = flag.String("format", "json", "Format of input file.") + configFiles CmdConfig // "Config file for V2Ray.", the option is customed type, parse in main + version = flag.Bool("version", false, "Show current version of V2Ray.") + test = flag.Bool("test", false, "Test config file only, without launching V2Ray server.") + format = flag.String("format", "json", "Format of input file.") ) func fileExists(file string) bool { @@ -30,23 +42,24 @@ func fileExists(file string) bool { return err == nil && !info.IsDir() } -func getConfigFilePath() string { - if len(*configFile) > 0 { - return *configFile +func getConfigFilePath() CmdConfig { + + if len(configFiles) > 0 { + return configFiles } if workingDir, err := os.Getwd(); err == nil { configFile := filepath.Join(workingDir, "config.json") if fileExists(configFile) { - return configFile + return []string{configFile} } } if configFile := platform.GetConfigurationPath(); fileExists(configFile) { - return configFile + return []string{configFile} } - return "" + return []string{} } func GetConfigFormat() string { @@ -59,16 +72,11 @@ func GetConfigFormat() string { } func startV2Ray() (core.Server, error) { - configFile := getConfigFilePath() - configInput, err := confloader.LoadConfig(configFile) + configFiles := getConfigFilePath() + fs, _ := json.Marshal(configFiles) + config, err := core.LoadConfig(GetConfigFormat(), configFiles[0], bytes.NewBuffer(fs)) if err != nil { - return nil, newError("failed to load config: ", configFile).Base(err) - } - defer configInput.Close() - - config, err := core.LoadConfig(GetConfigFormat(), configFile, configInput) - if err != nil { - return nil, newError("failed to read config file: ", configFile).Base(err) + return nil, newError("failed to read config files: [", configFiles.String(), "]").Base(err) } server, err := core.New(config) @@ -87,6 +95,7 @@ func printVersion() { } func main() { + flag.Var(&configFiles, "config", "Config file for V2Ray. Multiple assign is accepted (only json). Latter ones overrides the former ones.") flag.Parse() printVersion()