github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/config.go (about) 1 // +build !confonly 2 3 package core 4 5 import ( 6 "io" 7 "strings" 8 9 "github.com/golang/protobuf/proto" 10 "v2ray.com/core/common" 11 "v2ray.com/core/common/buf" 12 "v2ray.com/core/common/cmdarg" 13 "v2ray.com/core/main/confloader" 14 ) 15 16 // ConfigFormat is a configurable format of V2Ray config file. 17 type ConfigFormat struct { 18 Name string 19 Extension []string 20 Loader ConfigLoader 21 } 22 23 // ConfigLoader is a utility to load V2Ray config from external source. 24 type ConfigLoader func(input interface{}) (*Config, error) 25 26 var ( 27 configLoaderByName = make(map[string]*ConfigFormat) 28 configLoaderByExt = make(map[string]*ConfigFormat) 29 ) 30 31 // RegisterConfigLoader add a new ConfigLoader. 32 func RegisterConfigLoader(format *ConfigFormat) error { 33 name := strings.ToLower(format.Name) 34 if _, found := configLoaderByName[name]; found { 35 return newError(format.Name, " already registered.") 36 } 37 configLoaderByName[name] = format 38 39 for _, ext := range format.Extension { 40 lext := strings.ToLower(ext) 41 if f, found := configLoaderByExt[lext]; found { 42 return newError(ext, " already registered to ", f.Name) 43 } 44 configLoaderByExt[lext] = format 45 } 46 47 return nil 48 } 49 50 func getExtension(filename string) string { 51 idx := strings.LastIndexByte(filename, '.') 52 if idx == -1 { 53 return "" 54 } 55 return filename[idx+1:] 56 } 57 58 // LoadConfig loads config with given format from given source. 59 // input accepts 2 different types: 60 // * []string slice of multiple filename/url(s) to open to read 61 // * io.Reader that reads a config content (the original way) 62 func LoadConfig(formatName string, filename string, input interface{}) (*Config, error) { 63 ext := getExtension(filename) 64 if len(ext) > 0 { 65 if f, found := configLoaderByExt[ext]; found { 66 return f.Loader(input) 67 } 68 } 69 70 if f, found := configLoaderByName[formatName]; found { 71 return f.Loader(input) 72 } 73 74 return nil, newError("Unable to load config in ", formatName).AtWarning() 75 } 76 77 func loadProtobufConfig(data []byte) (*Config, error) { 78 config := new(Config) 79 if err := proto.Unmarshal(data, config); err != nil { 80 return nil, err 81 } 82 return config, nil 83 } 84 85 func init() { 86 common.Must(RegisterConfigLoader(&ConfigFormat{ 87 Name: "Protobuf", 88 Extension: []string{"pb"}, 89 Loader: func(input interface{}) (*Config, error) { 90 switch v := input.(type) { 91 case cmdarg.Arg: 92 r, err := confloader.LoadConfig(v[0]) 93 common.Must(err) 94 data, err := buf.ReadAllToBytes(r) 95 common.Must(err) 96 return loadProtobufConfig(data) 97 case io.Reader: 98 data, err := buf.ReadAllToBytes(v) 99 common.Must(err) 100 return loadProtobufConfig(data) 101 default: 102 return nil, newError("unknow type") 103 } 104 }, 105 })) 106 }