mirror of https://github.com/XTLS/Xray-core
150 lines
3.5 KiB
Go
150 lines
3.5 KiB
Go
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, errors.New("failed to read config file at line ", pos.line, " char ", pos.char).Base(err)
|
|
}
|
|
return nil, errors.New("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, errors.New("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, errors.New("failed to read config file").Base(err)
|
|
}
|
|
|
|
configMap := make(map[string]interface{})
|
|
if err := toml.Unmarshal(tomlFile, &configMap); err != nil {
|
|
return nil, errors.New("failed to convert toml to map").Base(err)
|
|
}
|
|
|
|
jsonFile, err := json.Marshal(&configMap)
|
|
if err != nil {
|
|
return nil, errors.New("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, errors.New("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, errors.New("failed to read config file").Base(err)
|
|
}
|
|
|
|
jsonFile, err := yaml.YAMLToJSON(yamlFile)
|
|
if err != nil {
|
|
return nil, errors.New("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, errors.New("failed to parse yaml config").Base(err)
|
|
}
|
|
|
|
return pbConfig, nil
|
|
}
|