2019-02-10 13:04:11 -05:00
|
|
|
package serial
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/json"
|
2021-06-19 08:45:43 -04:00
|
|
|
"github.com/v2fly/v2ray-core/v4/infra/conf/v4"
|
2019-02-10 13:04:11 -05:00
|
|
|
"io"
|
|
|
|
|
2021-02-16 15:31:50 -05:00
|
|
|
core "github.com/v2fly/v2ray-core/v4"
|
|
|
|
"github.com/v2fly/v2ray-core/v4/common/errors"
|
|
|
|
json_reader "github.com/v2fly/v2ray-core/v4/infra/conf/json"
|
2019-02-10 13:04:11 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
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}
|
|
|
|
}
|
|
|
|
|
2020-01-02 20:26:48 -05:00
|
|
|
// DecodeJSONConfig reads from reader and decode the config into *conf.Config
|
|
|
|
// syntax error could be detected.
|
2021-06-19 08:45:43 -04:00
|
|
|
func DecodeJSONConfig(reader io.Reader) (*v4.Config, error) {
|
|
|
|
jsonConfig := &v4.Config{}
|
2020-11-28 09:06:03 -05:00
|
|
|
err := DecodeJSON(reader, jsonConfig)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return jsonConfig, nil
|
|
|
|
}
|
2019-02-10 13:04:11 -05:00
|
|
|
|
2020-11-28 09:06:03 -05:00
|
|
|
// DecodeJSON reads from reader and decode into target
|
|
|
|
// syntax error could be detected.
|
|
|
|
func DecodeJSON(reader io.Reader, target interface{}) error {
|
2019-02-10 13:04:11 -05:00
|
|
|
jsonContent := bytes.NewBuffer(make([]byte, 0, 10240))
|
|
|
|
jsonReader := io.TeeReader(&json_reader.Reader{
|
|
|
|
Reader: reader,
|
|
|
|
}, jsonContent)
|
|
|
|
decoder := json.NewDecoder(jsonReader)
|
|
|
|
|
2020-11-28 09:06:03 -05:00
|
|
|
if err := decoder.Decode(target); err != nil {
|
2019-02-10 13:04:11 -05:00
|
|
|
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 {
|
2020-11-28 09:06:03 -05:00
|
|
|
return newError("failed to read config file at line ", pos.line, " char ", pos.char).Base(err)
|
2019-02-10 13:04:11 -05:00
|
|
|
}
|
2020-11-28 09:06:03 -05:00
|
|
|
return newError("failed to read config file").Base(err)
|
2019-02-10 13:04:11 -05:00
|
|
|
}
|
|
|
|
|
2020-11-28 09:06:03 -05:00
|
|
|
return nil
|
2020-01-02 20:26:48 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func LoadJSONConfig(reader io.Reader) (*core.Config, error) {
|
|
|
|
jsonConfig, err := DecodeJSONConfig(reader)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-02-10 13:04:11 -05:00
|
|
|
pbConfig, err := jsonConfig.Build()
|
|
|
|
if err != nil {
|
|
|
|
return nil, newError("failed to parse json config").Base(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return pbConfig, nil
|
|
|
|
}
|