config.go 2.0 KB

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