Browse Source

main loads multiple

vcptr 6 years ago
parent
commit
1e76123a4c

+ 3 - 1
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

+ 1 - 1
infra/control/mconfig.go → 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 {

+ 0 - 19
main/confloader/confloader.go

@@ -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)
-}

+ 0 - 48
main/confloader/external/external.go

@@ -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
-}

+ 0 - 3
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"
 )

+ 6 - 1
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()
 			}

+ 1 - 1
main/confloader/external/errors.generated.go → main/jsonem/errors.generated.go

@@ -1,4 +1,4 @@
-package external
+package jsonem
 
 import "v2ray.com/core/common/errors"
 

+ 78 - 2
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
 }

+ 29 - 20
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)
-	if err != nil {
-		return nil, newError("failed to load config: ", configFile).Base(err)
-	}
-	defer configInput.Close()
-
-	config, err := core.LoadConfig(GetConfigFormat(), configFile, configInput)
+	configFiles := getConfigFilePath()
+	fs, _ := json.Marshal(configFiles)
+	config, err := core.LoadConfig(GetConfigFormat(), configFiles[0], bytes.NewBuffer(fs))
 	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()