config.go 2.0 KB

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