mirror of
https://github.com/v2fly/v2ray-core.git
synced 2025-01-14 21:36:25 -05:00
abstract type for conf load func
This commit is contained in:
parent
61e95e06c0
commit
1bb34bfe17
14
common/cmdarg/cmdarg.go
Normal file
14
common/cmdarg/cmdarg.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package cmdarg
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
type Arg []string
|
||||||
|
|
||||||
|
func (c *Arg) String() string {
|
||||||
|
return strings.Join([]string(*c), " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Arg) Set(value string) error {
|
||||||
|
*c = append(*c, value)
|
||||||
|
return nil
|
||||||
|
}
|
34
config.go
34
config.go
@ -4,11 +4,13 @@ package core
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
|
"v2ray.com/core/common/cmdarg"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ConfigFormat is a configurable format of V2Ray config file.
|
// ConfigFormat is a configurable format of V2Ray config file.
|
||||||
@ -19,7 +21,7 @@ type ConfigFormat struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ConfigLoader is a utility to load V2Ray config from external source.
|
// ConfigLoader is a utility to load V2Ray config from external source.
|
||||||
type ConfigLoader func(input io.Reader) (*Config, error)
|
type ConfigLoader func(input interface{}) (*Config, error)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
configLoaderByName = make(map[string]*ConfigFormat)
|
configLoaderByName = make(map[string]*ConfigFormat)
|
||||||
@ -54,7 +56,10 @@ func getExtension(filename string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LoadConfig loads config with given format from given source.
|
// LoadConfig loads config with given format from given source.
|
||||||
func LoadConfig(formatName string, filename string, input io.Reader) (*Config, error) {
|
// input accepts 2 different types:
|
||||||
|
// * []string slice of multiple filename/url(s) to open to read
|
||||||
|
// * io.Reader that reads a config content (the original way)
|
||||||
|
func LoadConfig(formatName string, filename string, input interface{}) (*Config, error) {
|
||||||
ext := getExtension(filename)
|
ext := getExtension(filename)
|
||||||
if len(ext) > 0 {
|
if len(ext) > 0 {
|
||||||
if f, found := configLoaderByExt[ext]; found {
|
if f, found := configLoaderByExt[ext]; found {
|
||||||
@ -69,12 +74,8 @@ func LoadConfig(formatName string, filename string, input io.Reader) (*Config, e
|
|||||||
return nil, newError("Unable to load config in ", formatName).AtWarning()
|
return nil, newError("Unable to load config in ", formatName).AtWarning()
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadProtobufConfig(input io.Reader) (*Config, error) {
|
func loadProtobufConfig(data []byte) (*Config, error) {
|
||||||
config := new(Config)
|
config := new(Config)
|
||||||
data, err := buf.ReadAllToBytes(input)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := proto.Unmarshal(data, config); err != nil {
|
if err := proto.Unmarshal(data, config); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -85,6 +86,23 @@ func init() {
|
|||||||
common.Must(RegisterConfigLoader(&ConfigFormat{
|
common.Must(RegisterConfigLoader(&ConfigFormat{
|
||||||
Name: "Protobuf",
|
Name: "Protobuf",
|
||||||
Extension: []string{"pb"},
|
Extension: []string{"pb"},
|
||||||
Loader: loadProtobufConfig,
|
Loader: func(input interface{}) (*Config, error) {
|
||||||
|
switch v := input.(type) {
|
||||||
|
case cmdarg.Arg:
|
||||||
|
if len(v) == 0 {
|
||||||
|
return nil, newError("input has no element")
|
||||||
|
}
|
||||||
|
// pb type can only handle the first config
|
||||||
|
data, err := ioutil.ReadFile(v[0])
|
||||||
|
common.Must(err)
|
||||||
|
return loadProtobufConfig(data)
|
||||||
|
case io.Reader:
|
||||||
|
data, err := buf.ReadAllToBytes(v)
|
||||||
|
common.Must(err)
|
||||||
|
return loadProtobufConfig(data)
|
||||||
|
default:
|
||||||
|
return nil, newError("unknow type")
|
||||||
|
}
|
||||||
|
},
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -3,31 +3,35 @@ package json
|
|||||||
//go:generate errorgen
|
//go:generate errorgen
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
|
|
||||||
"v2ray.com/core"
|
"v2ray.com/core"
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
|
"v2ray.com/core/common/cmdarg"
|
||||||
"v2ray.com/core/common/platform/ctlcmd"
|
"v2ray.com/core/common/platform/ctlcmd"
|
||||||
|
"v2ray.com/core/infra/conf/serial"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
common.Must(core.RegisterConfigLoader(&core.ConfigFormat{
|
common.Must(core.RegisterConfigLoader(&core.ConfigFormat{
|
||||||
Name: "JSON",
|
Name: "JSON",
|
||||||
Extension: []string{"json"},
|
Extension: []string{"json"},
|
||||||
Loader: func(input io.Reader) (*core.Config, error) {
|
Loader: func(input interface{}) (*core.Config, error) {
|
||||||
fns := []string{}
|
switch v := input.(type) {
|
||||||
data, _ := ioutil.ReadAll(input)
|
case cmdarg.Arg:
|
||||||
json.Unmarshal(data, &fns)
|
jsonContent, err := ctlcmd.Run(append([]string{"config"}, v...), nil)
|
||||||
jsonContent, err := ctlcmd.Run(append([]string{"config"}, fns...), nil)
|
if err != nil {
|
||||||
if err != nil {
|
return nil, newError("failed to execute v2ctl to convert config file.").Base(err).AtWarning()
|
||||||
return nil, newError("failed to execute v2ctl to convert config file.").Base(err).AtWarning()
|
}
|
||||||
|
return core.LoadConfig("protobuf", "", &buf.MultiBufferContainer{
|
||||||
|
MultiBuffer: jsonContent,
|
||||||
|
})
|
||||||
|
case io.Reader:
|
||||||
|
return serial.LoadJSONConfig(v)
|
||||||
|
default:
|
||||||
|
return nil, newError("unknow type")
|
||||||
}
|
}
|
||||||
return core.LoadConfig("protobuf", "", &buf.MultiBufferContainer{
|
|
||||||
MultiBuffer: jsonContent,
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package jsonem
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -13,6 +12,7 @@ import (
|
|||||||
"v2ray.com/core"
|
"v2ray.com/core"
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/common/buf"
|
"v2ray.com/core/common/buf"
|
||||||
|
"v2ray.com/core/common/cmdarg"
|
||||||
"v2ray.com/core/infra/conf"
|
"v2ray.com/core/infra/conf"
|
||||||
"v2ray.com/core/infra/conf/serial"
|
"v2ray.com/core/infra/conf/serial"
|
||||||
)
|
)
|
||||||
@ -21,21 +21,25 @@ func init() {
|
|||||||
common.Must(core.RegisterConfigLoader(&core.ConfigFormat{
|
common.Must(core.RegisterConfigLoader(&core.ConfigFormat{
|
||||||
Name: "JSON",
|
Name: "JSON",
|
||||||
Extension: []string{"json"},
|
Extension: []string{"json"},
|
||||||
Loader: func(input io.Reader) (*core.Config, error) {
|
Loader: func(input interface{}) (*core.Config, error) {
|
||||||
fns := []string{}
|
switch v := input.(type) {
|
||||||
data, _ := ioutil.ReadAll(input)
|
case cmdarg.Arg:
|
||||||
json.Unmarshal(data, &fns)
|
cf := &conf.Config{}
|
||||||
|
for _, arg := range v {
|
||||||
cf := &conf.Config{}
|
r, err := LoadArg(arg)
|
||||||
for _, arg := range fns {
|
common.Must(err)
|
||||||
r, err := LoadArg(arg)
|
c, err := serial.DecodeJSONConfig(r)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
c, err := serial.DecodeJSONConfig(r)
|
cf.Override(c, arg)
|
||||||
common.Must(err)
|
}
|
||||||
cf.Override(c, arg)
|
return cf.Build()
|
||||||
|
case io.Reader:
|
||||||
|
return serial.LoadJSONConfig(v)
|
||||||
|
default:
|
||||||
|
return nil, newError("unknow type")
|
||||||
}
|
}
|
||||||
return cf.Build()
|
},
|
||||||
}}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadArg(arg string) (out io.Reader, err error) {
|
func LoadArg(arg string) (out io.Reader, err error) {
|
||||||
|
42
main/main.go
42
main/main.go
@ -3,8 +3,6 @@ package main
|
|||||||
//go:generate errorgen
|
//go:generate errorgen
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
@ -15,26 +13,17 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"v2ray.com/core"
|
"v2ray.com/core"
|
||||||
|
"v2ray.com/core/common/cmdarg"
|
||||||
"v2ray.com/core/common/platform"
|
"v2ray.com/core/common/platform"
|
||||||
_ "v2ray.com/core/main/distro/all"
|
_ "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 (
|
var (
|
||||||
configFiles CmdConfig // "Config file for V2Ray.", the option is customed type, parse in main
|
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.")
|
version = flag.Bool("version", false, "Show current version of V2Ray.")
|
||||||
test = flag.Bool("test", false, "Test config file only, without launching V2Ray server.")
|
test = flag.Bool("test", false, "Test config file only, without launching V2Ray server.")
|
||||||
format = flag.String("format", "json", "Format of input file.")
|
format = flag.String("format", "", "Format of input file.")
|
||||||
|
errNoConfig = newError("no valid config")
|
||||||
)
|
)
|
||||||
|
|
||||||
func fileExists(file string) bool {
|
func fileExists(file string) bool {
|
||||||
@ -42,8 +31,7 @@ func fileExists(file string) bool {
|
|||||||
return err == nil && !info.IsDir()
|
return err == nil && !info.IsDir()
|
||||||
}
|
}
|
||||||
|
|
||||||
func getConfigFilePath() CmdConfig {
|
func getConfigFilePath() cmdarg.Arg {
|
||||||
|
|
||||||
if len(configFiles) > 0 {
|
if len(configFiles) > 0 {
|
||||||
return configFiles
|
return configFiles
|
||||||
}
|
}
|
||||||
@ -51,15 +39,15 @@ func getConfigFilePath() CmdConfig {
|
|||||||
if workingDir, err := os.Getwd(); err == nil {
|
if workingDir, err := os.Getwd(); err == nil {
|
||||||
configFile := filepath.Join(workingDir, "config.json")
|
configFile := filepath.Join(workingDir, "config.json")
|
||||||
if fileExists(configFile) {
|
if fileExists(configFile) {
|
||||||
return []string{configFile}
|
return cmdarg.Arg{configFile}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if configFile := platform.GetConfigurationPath(); fileExists(configFile) {
|
if configFile := platform.GetConfigurationPath(); fileExists(configFile) {
|
||||||
return []string{configFile}
|
return cmdarg.Arg{configFile}
|
||||||
}
|
}
|
||||||
|
|
||||||
return []string{}
|
return configFiles
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetConfigFormat() string {
|
func GetConfigFormat() string {
|
||||||
@ -73,8 +61,14 @@ func GetConfigFormat() string {
|
|||||||
|
|
||||||
func startV2Ray() (core.Server, error) {
|
func startV2Ray() (core.Server, error) {
|
||||||
configFiles := getConfigFilePath()
|
configFiles := getConfigFilePath()
|
||||||
fs, _ := json.Marshal(configFiles)
|
if len(configFiles) == 0 {
|
||||||
config, err := core.LoadConfig(GetConfigFormat(), configFiles[0], bytes.NewBuffer(fs))
|
if *format == "" {
|
||||||
|
return nil, errNoConfig
|
||||||
|
}
|
||||||
|
configFiles = []string{"stdin:"}
|
||||||
|
}
|
||||||
|
|
||||||
|
config, err := core.LoadConfig(GetConfigFormat(), configFiles[0], configFiles)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, newError("failed to read config files: [", configFiles.String(), "]").Base(err)
|
return nil, newError("failed to read config files: [", configFiles.String(), "]").Base(err)
|
||||||
}
|
}
|
||||||
@ -96,6 +90,7 @@ func printVersion() {
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Var(&configFiles, "config", "Config file for V2Ray. Multiple assign is accepted (only json). Latter ones overrides the former ones.")
|
flag.Var(&configFiles, "config", "Config file for V2Ray. Multiple assign is accepted (only json). Latter ones overrides the former ones.")
|
||||||
|
flag.Var(&configFiles, "c", "short alias of -config")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
printVersion()
|
printVersion()
|
||||||
@ -108,6 +103,9 @@ func main() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err.Error())
|
fmt.Println(err.Error())
|
||||||
// Configuration error. Exit with a special value to prevent systemd from restarting.
|
// Configuration error. Exit with a special value to prevent systemd from restarting.
|
||||||
|
if err == errNoConfig {
|
||||||
|
flag.PrintDefaults()
|
||||||
|
}
|
||||||
os.Exit(23)
|
os.Exit(23)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user