config.go 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. package core
  2. import (
  3. "io"
  4. "strings"
  5. "github.com/golang/protobuf/proto"
  6. "v2ray.com/core/common"
  7. "v2ray.com/core/common/buf"
  8. )
  9. // ConfigFormat is a configurable format of V2Ray config file.
  10. type ConfigFormat struct {
  11. Name string
  12. Extension []string
  13. Loader ConfigLoader
  14. }
  15. // ConfigLoader is a utility to load V2Ray config from external source.
  16. type ConfigLoader func(input io.Reader) (*Config, error)
  17. var (
  18. configLoaderByName = make(map[string]*ConfigFormat)
  19. configLoaderByExt = make(map[string]*ConfigFormat)
  20. )
  21. // RegisterConfigLoader add a new ConfigLoader.
  22. func RegisterConfigLoader(format *ConfigFormat) error {
  23. name := strings.ToLower(format.Name)
  24. if _, found := configLoaderByName[name]; found {
  25. return newError(format.Name, " already registered.")
  26. }
  27. configLoaderByName[name] = format
  28. for _, ext := range format.Extension {
  29. lext := strings.ToLower(ext)
  30. if f, found := configLoaderByExt[lext]; found {
  31. return newError(ext, " already registered to ", f.Name)
  32. }
  33. configLoaderByExt[lext] = format
  34. }
  35. return nil
  36. }
  37. func getExtension(filename string) string {
  38. idx := strings.LastIndexByte(filename, '.')
  39. if idx == -1 {
  40. return ""
  41. }
  42. return filename[idx+1:]
  43. }
  44. // LoadConfig loads config with given format from given source.
  45. func LoadConfig(formatName string, filename string, input io.Reader) (*Config, error) {
  46. ext := getExtension(filename)
  47. if len(ext) > 0 {
  48. if f, found := configLoaderByExt[ext]; found {
  49. return f.Loader(input)
  50. }
  51. }
  52. if f, found := configLoaderByName[formatName]; found {
  53. return f.Loader(input)
  54. }
  55. return nil, newError("Unable to load config in ", formatName).AtWarning()
  56. }
  57. func loadProtobufConfig(input io.Reader) (*Config, error) {
  58. config := new(Config)
  59. data, err := buf.ReadAllToBytes(input)
  60. if err != nil {
  61. return nil, err
  62. }
  63. if err := proto.Unmarshal(data, config); err != nil {
  64. return nil, err
  65. }
  66. return config, nil
  67. }
  68. func init() {
  69. common.Must(RegisterConfigLoader(&ConfigFormat{
  70. Name: "Protobuf",
  71. Extension: []string{"pb"},
  72. Loader: loadProtobufConfig,
  73. }))
  74. }