mirror of https://github.com/XTLS/Xray-core
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
149 lines
3.5 KiB
149 lines
3.5 KiB
package serial |
|
|
|
import ( |
|
"bytes" |
|
"encoding/json" |
|
"io" |
|
|
|
"github.com/ghodss/yaml" |
|
"github.com/pelletier/go-toml" |
|
"github.com/xtls/xray-core/common/errors" |
|
"github.com/xtls/xray-core/core" |
|
"github.com/xtls/xray-core/infra/conf" |
|
json_reader "github.com/xtls/xray-core/infra/conf/json" |
|
) |
|
|
|
type offset struct { |
|
line int |
|
char int |
|
} |
|
|
|
func findOffset(b []byte, o int) *offset { |
|
if o >= len(b) || o < 0 { |
|
return nil |
|
} |
|
|
|
line := 1 |
|
char := 0 |
|
for i, x := range b { |
|
if i == o { |
|
break |
|
} |
|
if x == '\n' { |
|
line++ |
|
char = 0 |
|
} else { |
|
char++ |
|
} |
|
} |
|
|
|
return &offset{line: line, char: char} |
|
} |
|
|
|
// DecodeJSONConfig reads from reader and decode the config into *conf.Config |
|
// syntax error could be detected. |
|
func DecodeJSONConfig(reader io.Reader) (*conf.Config, error) { |
|
jsonConfig := &conf.Config{} |
|
|
|
jsonContent := bytes.NewBuffer(make([]byte, 0, 10240)) |
|
jsonReader := io.TeeReader(&json_reader.Reader{ |
|
Reader: reader, |
|
}, jsonContent) |
|
decoder := json.NewDecoder(jsonReader) |
|
|
|
if err := decoder.Decode(jsonConfig); err != nil { |
|
var pos *offset |
|
cause := errors.Cause(err) |
|
switch tErr := cause.(type) { |
|
case *json.SyntaxError: |
|
pos = findOffset(jsonContent.Bytes(), int(tErr.Offset)) |
|
case *json.UnmarshalTypeError: |
|
pos = findOffset(jsonContent.Bytes(), int(tErr.Offset)) |
|
} |
|
if pos != nil { |
|
return nil, newError("failed to read config file at line ", pos.line, " char ", pos.char).Base(err) |
|
} |
|
return nil, newError("failed to read config file").Base(err) |
|
} |
|
|
|
return jsonConfig, nil |
|
} |
|
|
|
func LoadJSONConfig(reader io.Reader) (*core.Config, error) { |
|
jsonConfig, err := DecodeJSONConfig(reader) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
pbConfig, err := jsonConfig.Build() |
|
if err != nil { |
|
return nil, newError("failed to parse json config").Base(err) |
|
} |
|
|
|
return pbConfig, nil |
|
} |
|
|
|
// DecodeTOMLConfig reads from reader and decode the config into *conf.Config |
|
// using github.com/pelletier/go-toml and map to convert toml to json. |
|
func DecodeTOMLConfig(reader io.Reader) (*conf.Config, error) { |
|
tomlFile, err := io.ReadAll(reader) |
|
if err != nil { |
|
return nil, newError("failed to read config file").Base(err) |
|
} |
|
|
|
configMap := make(map[string]interface{}) |
|
if err := toml.Unmarshal(tomlFile, &configMap); err != nil { |
|
return nil, newError("failed to convert toml to map").Base(err) |
|
} |
|
|
|
jsonFile, err := json.Marshal(&configMap) |
|
if err != nil { |
|
return nil, newError("failed to convert map to json").Base(err) |
|
} |
|
|
|
return DecodeJSONConfig(bytes.NewReader(jsonFile)) |
|
} |
|
|
|
func LoadTOMLConfig(reader io.Reader) (*core.Config, error) { |
|
tomlConfig, err := DecodeTOMLConfig(reader) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
pbConfig, err := tomlConfig.Build() |
|
if err != nil { |
|
return nil, newError("failed to parse toml config").Base(err) |
|
} |
|
|
|
return pbConfig, nil |
|
} |
|
|
|
// DecodeYAMLConfig reads from reader and decode the config into *conf.Config |
|
// using github.com/ghodss/yaml to convert yaml to json. |
|
func DecodeYAMLConfig(reader io.Reader) (*conf.Config, error) { |
|
yamlFile, err := io.ReadAll(reader) |
|
if err != nil { |
|
return nil, newError("failed to read config file").Base(err) |
|
} |
|
|
|
jsonFile, err := yaml.YAMLToJSON(yamlFile) |
|
if err != nil { |
|
return nil, newError("failed to convert yaml to json").Base(err) |
|
} |
|
|
|
return DecodeJSONConfig(bytes.NewReader(jsonFile)) |
|
} |
|
|
|
func LoadYAMLConfig(reader io.Reader) (*core.Config, error) { |
|
yamlConfig, err := DecodeYAMLConfig(reader) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
pbConfig, err := yamlConfig.Build() |
|
if err != nil { |
|
return nil, newError("failed to parse yaml config").Base(err) |
|
} |
|
|
|
return pbConfig, nil |
|
}
|
|
|