Browse Source

rearrange loader

vcptr 6 years ago
parent
commit
f14eb97e3c

+ 5 - 14
config.go

@@ -4,14 +4,13 @@ package core
 
 import (
 	"io"
-	"io/ioutil"
-	"os"
 	"strings"
 
 	"github.com/golang/protobuf/proto"
 	"v2ray.com/core/common"
 	"v2ray.com/core/common/buf"
 	"v2ray.com/core/common/cmdarg"
+	"v2ray.com/core/main/confloader"
 )
 
 // ConfigFormat is a configurable format of V2Ray config file.
@@ -90,18 +89,10 @@ func init() {
 		Loader: func(input interface{}) (*Config, error) {
 			switch v := input.(type) {
 			case cmdarg.Arg:
-				if len(v) == 0 {
-					return nil, newError("input has no element")
-				}
-				var data []byte
-				var rerr error
-				// pb type can only handle the first config
-				if v[0] == "stdin:" {
-					data, rerr = buf.ReadAllToBytes(os.Stdin)
-				} else {
-					data, rerr = ioutil.ReadFile(v[0])
-				}
-				common.Must(rerr)
+				r, err := confloader.LoadConfig(v[0])
+				common.Must(err)
+				data, err := buf.ReadAllToBytes(r)
+				common.Must(err)
 				return loadProtobufConfig(data)
 			case io.Reader:
 				data, err := buf.ReadAllToBytes(v)

+ 30 - 0
main/confloader/confloader.go

@@ -0,0 +1,30 @@
+package confloader
+
+import (
+	"io"
+	"os"
+)
+
+type configFileLoader func(string) (io.Reader, error)
+type extconfigLoader func([]string) (io.Reader, error)
+
+var (
+	EffectiveConfigFileLoader configFileLoader
+	EffectiveExtConfigLoader  extconfigLoader
+)
+
+func LoadConfig(file string) (io.Reader, error) {
+	if EffectiveConfigFileLoader == nil {
+		newError("external config module not loaded, reading from stdin").AtInfo().WriteToLog()
+		return os.Stdin, nil
+	}
+	return EffectiveConfigFileLoader(file)
+}
+
+func LoadExtConfig(files []string) (io.Reader, error) {
+	if EffectiveExtConfigLoader == nil {
+		return nil, newError("external config module not loaded").AtError()
+	}
+
+	return EffectiveExtConfigLoader(files)
+}

+ 9 - 0
main/confloader/errors.generated.go

@@ -0,0 +1,9 @@
+package confloader
+
+import "v2ray.com/core/common/errors"
+
+type errPathObjHolder struct{}
+
+func newError(values ...interface{}) *errors.Error {
+	return errors.New(values...).WithPathObj(errPathObjHolder{})
+}

+ 9 - 0
main/confloader/external/errors.generated.go

@@ -0,0 +1,9 @@
+package external
+
+import "v2ray.com/core/common/errors"
+
+type errPathObjHolder struct{}
+
+func newError(values ...interface{}) *errors.Error {
+	return errors.New(values...).WithPathObj(errPathObjHolder{})
+}

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

@@ -0,0 +1,86 @@
+package external
+
+//go:generate errorgen
+
+import (
+	"bytes"
+	"io"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"os"
+	"strings"
+	"time"
+
+	"v2ray.com/core/common/buf"
+	"v2ray.com/core/common/platform/ctlcmd"
+	"v2ray.com/core/main/confloader"
+)
+
+func ConfigLoader(arg string) (out io.Reader, err error) {
+
+	var data []byte
+	if strings.HasPrefix(arg, "http://") || strings.HasPrefix(arg, "https://") {
+		data, err = FetchHTTPContent(arg)
+	} else if arg == "stdin:" {
+		data, err = ioutil.ReadAll(os.Stdin)
+	} 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
+}
+
+func ExtConfigLoader(files []string) (io.Reader, error) {
+	buf, err := ctlcmd.Run(append([]string{"config"}, files...), os.Stdin)
+	if err != nil {
+		return nil, err
+	}
+
+	return strings.NewReader(buf.String()), nil
+}
+
+func init() {
+	confloader.EffectiveConfigFileLoader = ConfigLoader
+	confloader.EffectiveExtConfigLoader = ExtConfigLoader
+}

+ 3 - 0
main/distro/all/all.go

@@ -58,4 +58,7 @@ 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"
 )

+ 3 - 7
main/json/config_json.go

@@ -4,14 +4,12 @@ package json
 
 import (
 	"io"
-	"os"
 
 	"v2ray.com/core"
 	"v2ray.com/core/common"
-	"v2ray.com/core/common/buf"
 	"v2ray.com/core/common/cmdarg"
-	"v2ray.com/core/common/platform/ctlcmd"
 	"v2ray.com/core/infra/conf/serial"
+	"v2ray.com/core/main/confloader"
 )
 
 func init() {
@@ -21,13 +19,11 @@ func init() {
 		Loader: func(input interface{}) (*core.Config, error) {
 			switch v := input.(type) {
 			case cmdarg.Arg:
-				jsonContent, err := ctlcmd.Run(append([]string{"config"}, v...), os.Stdin)
+				r, err := confloader.LoadExtConfig(v)
 				if err != nil {
 					return nil, newError("failed to execute v2ctl to convert config file.").Base(err).AtWarning()
 				}
-				return core.LoadConfig("protobuf", "", &buf.MultiBufferContainer{
-					MultiBuffer: jsonContent,
-				})
+				return core.LoadConfig("protobuf", "", r)
 			case io.Reader:
 				return serial.LoadJSONConfig(v)
 			default:

+ 2 - 63
main/jsonem/jsonem.go

@@ -1,21 +1,14 @@
 package jsonem
 
 import (
-	"bytes"
 	"io"
-	"io/ioutil"
-	"net/http"
-	"net/url"
-	"os"
-	"strings"
-	"time"
 
 	"v2ray.com/core"
 	"v2ray.com/core/common"
-	"v2ray.com/core/common/buf"
 	"v2ray.com/core/common/cmdarg"
 	"v2ray.com/core/infra/conf"
 	"v2ray.com/core/infra/conf/serial"
+	"v2ray.com/core/main/confloader"
 )
 
 func init() {
@@ -28,7 +21,7 @@ func init() {
 				cf := &conf.Config{}
 				for _, arg := range v {
 					newError("Reading config: ", arg).AtInfo().WriteToLog()
-					r, err := LoadArg(arg)
+					r, err := confloader.LoadConfig(arg)
 					common.Must(err)
 					c, err := serial.DecodeJSONConfig(r)
 					common.Must(err)
@@ -43,57 +36,3 @@ func init() {
 		},
 	}))
 }
-
-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 if arg == "stdin:" {
-		data, err = ioutil.ReadAll(os.Stdin)
-	} 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
-}

+ 9 - 12
main/main.go

@@ -22,7 +22,7 @@ var (
 	configFiles cmdarg.Arg // "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", "", "Format of input file.")
+	format      = flag.String("format", "json", "Format of input file.")
 	errNoConfig = newError("no valid config")
 )
 
@@ -31,23 +31,23 @@ func fileExists(file string) bool {
 	return err == nil && !info.IsDir()
 }
 
-func getConfigFilePath() cmdarg.Arg {
+func getConfigFilePath() (cmdarg.Arg, error) {
 	if len(configFiles) > 0 {
-		return configFiles
+		return configFiles, nil
 	}
 
 	if workingDir, err := os.Getwd(); err == nil {
 		configFile := filepath.Join(workingDir, "config.json")
 		if fileExists(configFile) {
-			return cmdarg.Arg{configFile}
+			return cmdarg.Arg{configFile}, nil
 		}
 	}
 
 	if configFile := platform.GetConfigurationPath(); fileExists(configFile) {
-		return cmdarg.Arg{configFile}
+		return cmdarg.Arg{configFile}, nil
 	}
 
-	return configFiles
+	return cmdarg.Arg{"stdin:"}, nil
 }
 
 func GetConfigFormat() string {
@@ -60,12 +60,9 @@ func GetConfigFormat() string {
 }
 
 func startV2Ray() (core.Server, error) {
-	configFiles := getConfigFilePath()
-	if len(configFiles) == 0 {
-		if *format == "" {
-			return nil, errNoConfig
-		}
-		configFiles = []string{"stdin:"}
+	configFiles, err := getConfigFilePath()
+	if err != nil {
+		return nil, err
 	}
 
 	config, err := core.LoadConfig(GetConfigFormat(), configFiles[0], configFiles)