loader.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. package serial
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "io"
  6. "io/ioutil"
  7. "github.com/ghodss/yaml"
  8. "github.com/pelletier/go-toml"
  9. "github.com/xtls/xray-core/common/errors"
  10. "github.com/xtls/xray-core/core"
  11. "github.com/xtls/xray-core/infra/conf"
  12. json_reader "github.com/xtls/xray-core/infra/conf/json"
  13. )
  14. type offset struct {
  15. line int
  16. char int
  17. }
  18. func findOffset(b []byte, o int) *offset {
  19. if o >= len(b) || o < 0 {
  20. return nil
  21. }
  22. line := 1
  23. char := 0
  24. for i, x := range b {
  25. if i == o {
  26. break
  27. }
  28. if x == '\n' {
  29. line++
  30. char = 0
  31. } else {
  32. char++
  33. }
  34. }
  35. return &offset{line: line, char: char}
  36. }
  37. // DecodeJSONConfig reads from reader and decode the config into *conf.Config
  38. // syntax error could be detected.
  39. func DecodeJSONConfig(reader io.Reader) (*conf.Config, error) {
  40. jsonConfig := &conf.Config{}
  41. jsonContent := bytes.NewBuffer(make([]byte, 0, 10240))
  42. jsonReader := io.TeeReader(&json_reader.Reader{
  43. Reader: reader,
  44. }, jsonContent)
  45. decoder := json.NewDecoder(jsonReader)
  46. if err := decoder.Decode(jsonConfig); err != nil {
  47. var pos *offset
  48. cause := errors.Cause(err)
  49. switch tErr := cause.(type) {
  50. case *json.SyntaxError:
  51. pos = findOffset(jsonContent.Bytes(), int(tErr.Offset))
  52. case *json.UnmarshalTypeError:
  53. pos = findOffset(jsonContent.Bytes(), int(tErr.Offset))
  54. }
  55. if pos != nil {
  56. return nil, newError("failed to read config file at line ", pos.line, " char ", pos.char).Base(err)
  57. }
  58. return nil, newError("failed to read config file").Base(err)
  59. }
  60. return jsonConfig, nil
  61. }
  62. func LoadJSONConfig(reader io.Reader) (*core.Config, error) {
  63. jsonConfig, err := DecodeJSONConfig(reader)
  64. if err != nil {
  65. return nil, err
  66. }
  67. pbConfig, err := jsonConfig.Build()
  68. if err != nil {
  69. return nil, newError("failed to parse json config").Base(err)
  70. }
  71. return pbConfig, nil
  72. }
  73. // DecodeTOMLConfig reads from reader and decode the config into *conf.Config
  74. // using github.com/pelletier/go-toml and map to convert toml to json.
  75. func DecodeTOMLConfig(reader io.Reader) (*conf.Config, error) {
  76. tomlFile, err := ioutil.ReadAll(reader)
  77. if err != nil {
  78. return nil, newError("failed to read config file").Base(err)
  79. }
  80. configMap := make(map[string]interface{})
  81. if err := toml.Unmarshal(tomlFile, &configMap); err != nil {
  82. return nil, newError("failed to convert toml to map").Base(err)
  83. }
  84. jsonFile, err := json.Marshal(&configMap)
  85. if err != nil {
  86. return nil, newError("failed to convert map to json").Base(err)
  87. }
  88. return DecodeJSONConfig(bytes.NewReader(jsonFile))
  89. }
  90. func LoadTOMLConfig(reader io.Reader) (*core.Config, error) {
  91. tomlConfig, err := DecodeTOMLConfig(reader)
  92. if err != nil {
  93. return nil, err
  94. }
  95. pbConfig, err := tomlConfig.Build()
  96. if err != nil {
  97. return nil, newError("failed to parse toml config").Base(err)
  98. }
  99. return pbConfig, nil
  100. }
  101. // DecodeYAMLConfig reads from reader and decode the config into *conf.Config
  102. // using github.com/ghodss/yaml to convert yaml to json.
  103. func DecodeYAMLConfig(reader io.Reader) (*conf.Config, error) {
  104. yamlFile, err := ioutil.ReadAll(reader)
  105. if err != nil {
  106. return nil, newError("failed to read config file").Base(err)
  107. }
  108. jsonFile, err := yaml.YAMLToJSON(yamlFile)
  109. if err != nil {
  110. return nil, newError("failed to convert yaml to json").Base(err)
  111. }
  112. return DecodeJSONConfig(bytes.NewReader(jsonFile))
  113. }
  114. func LoadYAMLConfig(reader io.Reader) (*core.Config, error) {
  115. yamlConfig, err := DecodeYAMLConfig(reader)
  116. if err != nil {
  117. return nil, err
  118. }
  119. pbConfig, err := yamlConfig.Build()
  120. if err != nil {
  121. return nil, newError("failed to parse yaml config").Base(err)
  122. }
  123. return pbConfig, nil
  124. }