mirror of
https://github.com/wyx2685/V2bX.git
synced 2025-01-22 09:58:14 -05:00
Merge remote-tracking branch 'origin/dev_new' into dev_new
This commit is contained in:
commit
5aab88629d
@ -2,6 +2,7 @@ package panel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/goccy/go-json"
|
||||
)
|
||||
@ -66,5 +67,6 @@ func (c *Client) ReportUserTraffic(userTraffic []UserTraffic) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Println(r.String())
|
||||
return nil
|
||||
}
|
||||
|
@ -1,19 +1,17 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/InazumaV/V2bX/conf"
|
||||
vCore "github.com/InazumaV/V2bX/core"
|
||||
"github.com/InazumaV/V2bX/limiter"
|
||||
"github.com/InazumaV/V2bX/node"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"gopkg.in/natefinch/lumberjack.v2"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime"
|
||||
"syscall"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
vCore "github.com/InazumaV/V2bX/core"
|
||||
|
||||
"github.com/InazumaV/V2bX/conf"
|
||||
"github.com/InazumaV/V2bX/limiter"
|
||||
"github.com/InazumaV/V2bX/node"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -56,6 +54,16 @@ func serverHandle(_ *cobra.Command, _ []string) {
|
||||
case "error":
|
||||
log.SetLevel(log.ErrorLevel)
|
||||
}
|
||||
if c.LogConfig.Output != "" {
|
||||
w := &lumberjack.Logger{
|
||||
Filename: c.LogConfig.Output,
|
||||
MaxSize: 100,
|
||||
MaxBackups: 3,
|
||||
MaxAge: 28,
|
||||
Compress: true,
|
||||
}
|
||||
log.SetOutput(w)
|
||||
}
|
||||
limiter.Init()
|
||||
log.Info("Start V2bX...")
|
||||
vc, err := vCore.NewCore(c.CoresConfig)
|
||||
|
112
common/json5/json5.go
Normal file
112
common/json5/json5.go
Normal file
@ -0,0 +1,112 @@
|
||||
package json5
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
type TrimNodeReader struct {
|
||||
r io.Reader
|
||||
br *bytes.Reader
|
||||
}
|
||||
|
||||
func isNL(c byte) bool {
|
||||
return c == '\n' || c == '\r'
|
||||
}
|
||||
|
||||
func isWS(c byte) bool {
|
||||
return c == ' ' || c == '\t' || isNL(c)
|
||||
}
|
||||
|
||||
func consumeComment(s []byte, i int) int {
|
||||
if i < len(s) && s[i] == '/' {
|
||||
s[i-1] = ' '
|
||||
for ; i < len(s) && !isNL(s[i]); i += 1 {
|
||||
s[i] = ' '
|
||||
}
|
||||
}
|
||||
if i < len(s) && s[i] == '*' {
|
||||
s[i-1] = ' '
|
||||
s[i] = ' '
|
||||
for ; i < len(s); i += 1 {
|
||||
if s[i] != '*' {
|
||||
s[i] = ' '
|
||||
} else {
|
||||
s[i] = ' '
|
||||
i++
|
||||
if i < len(s) {
|
||||
if s[i] == '/' {
|
||||
s[i] = ' '
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
func prep(r io.Reader) (s []byte, err error) {
|
||||
buf := &bytes.Buffer{}
|
||||
_, err = io.Copy(buf, r)
|
||||
s = buf.Bytes()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
i := 0
|
||||
for i < len(s) {
|
||||
switch s[i] {
|
||||
case '"':
|
||||
i += 1
|
||||
for i < len(s) {
|
||||
if s[i] == '"' {
|
||||
i += 1
|
||||
break
|
||||
} else if s[i] == '\\' {
|
||||
i += 1
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
case '/':
|
||||
i = consumeComment(s, i+1)
|
||||
case ',':
|
||||
j := i
|
||||
for {
|
||||
i += 1
|
||||
if i >= len(s) {
|
||||
break
|
||||
} else if s[i] == '}' || s[i] == ']' {
|
||||
s[j] = ' '
|
||||
break
|
||||
} else if s[i] == '/' {
|
||||
i = consumeComment(s, i+1)
|
||||
} else if !isWS(s[i]) {
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Read acts as a proxy for the underlying reader and cleans p
|
||||
// of comments and trailing commas preceeding ] and }
|
||||
// comments are delimitted by // up until the end the line
|
||||
func (st *TrimNodeReader) Read(p []byte) (n int, err error) {
|
||||
if st.br == nil {
|
||||
var s []byte
|
||||
if s, err = prep(st.r); err != nil {
|
||||
return
|
||||
}
|
||||
st.br = bytes.NewReader(s)
|
||||
}
|
||||
return st.br.Read(p)
|
||||
}
|
||||
|
||||
// NewTrimNodeReader New returns an io.Reader acting as proxy to r
|
||||
func NewTrimNodeReader(r io.Reader) io.Reader {
|
||||
return &TrimNodeReader{r: r}
|
||||
}
|
@ -2,6 +2,7 @@ package conf
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/InazumaV/V2bX/common/json5"
|
||||
"os"
|
||||
|
||||
"github.com/goccy/go-json"
|
||||
@ -28,5 +29,5 @@ func (p *Conf) LoadFromPath(filePath string) error {
|
||||
return fmt.Errorf("open config file error: %s", err)
|
||||
}
|
||||
defer f.Close()
|
||||
return json.NewDecoder(f).Decode(p)
|
||||
return json.NewDecoder(json5.NewTrimNodeReader(f)).Decode(p)
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
|
||||
func TestConf_LoadFromPath(t *testing.T) {
|
||||
c := New()
|
||||
t.Log(c.LoadFromPath("./config.json"), c.NodeConfig)
|
||||
t.Log(c.LoadFromPath("../example/config.json"), c.NodeConfig)
|
||||
}
|
||||
|
||||
func TestConf_Watch(t *testing.T) {
|
||||
|
@ -1,65 +1,93 @@
|
||||
{
|
||||
"Log": {
|
||||
"Level": "error"
|
||||
// V2bX 的日志配置,独立于各 Core 的 log 配置
|
||||
|
||||
// 日志等级,info, warn, error, none
|
||||
"Level": "error",
|
||||
// 日志输出路径,默认输出到标准输出
|
||||
"Output": ""
|
||||
},
|
||||
"Cores": [
|
||||
{
|
||||
// Core类型
|
||||
"Type": "sing",
|
||||
"Log": {
|
||||
// 同 SingBox log 部分配置
|
||||
|
||||
"Level": "error",
|
||||
"Timestamp": true
|
||||
}
|
||||
},{
|
||||
// More
|
||||
},
|
||||
{
|
||||
"Type": "xray",
|
||||
"Log": {
|
||||
// 同 Xray-core log 部分配置
|
||||
|
||||
"Level": "error"
|
||||
},
|
||||
"DnsConfigPath": "",
|
||||
...
|
||||
"DnsConfigPath": ""
|
||||
// More
|
||||
}
|
||||
],
|
||||
"Nodes": [
|
||||
// Node配置有两种写法
|
||||
{
|
||||
// 写法1
|
||||
|
||||
// Core类型
|
||||
"Core": "sing",
|
||||
// API接口地址
|
||||
"ApiHost": "http://127.0.0.1",
|
||||
// API密钥,即Token
|
||||
"ApiKey": "test",
|
||||
// 节点ID
|
||||
"NodeID": 33,
|
||||
// 节点类型
|
||||
"NodeType": "shadowsocks",
|
||||
// 请求超时时间
|
||||
"Timeout": 30,
|
||||
// 本地审计规则
|
||||
"RuleListPath": "",
|
||||
// 监听IP
|
||||
"ListenIP": "0.0.0.0",
|
||||
// 发送IP
|
||||
"SendIP": "0.0.0.0",
|
||||
"EnableProxyProtocol": true,
|
||||
"EnableTFO": true,
|
||||
...
|
||||
},{
|
||||
"ApiConfig": {
|
||||
"ApiHost": "http://127.0.0.1",
|
||||
"ApiKey": "test",
|
||||
"NodeID": 33,
|
||||
"Timeout": 30,
|
||||
"RuleListPath": ""
|
||||
},
|
||||
"Options": {
|
||||
"Core": "sing",
|
||||
"EnableProxyProtocol": true,
|
||||
"EnableTFO": true,
|
||||
...
|
||||
}
|
||||
},
|
||||
{
|
||||
"Core": "xray",
|
||||
"ApiHost": "http://127.0.0.1",
|
||||
"ApiKey": "test",
|
||||
"NodeID": 33,
|
||||
"NodeType": "shadowsocks",
|
||||
"Timeout": 30,
|
||||
"RuleListPath": "",
|
||||
"ListenIP": "0.0.0.0",
|
||||
"SendIP": "0.0.0.0",
|
||||
"EnableProxyProtocol": true,
|
||||
"EnableTFO": true,
|
||||
...
|
||||
// 开启 Proxy Protocol,参见 https://github.com/haproxy/haproxy/blob/master/doc/proxy-protocol.txt
|
||||
"EnableProxyProtocol": false,
|
||||
// 开启 TCP Fast Open
|
||||
"EnableTFO": true
|
||||
// More
|
||||
}
|
||||
/*,
|
||||
{
|
||||
// 写法2
|
||||
|
||||
"ApiConfig": {
|
||||
"ApiHost": "http://127.0.0.1",
|
||||
"ApiKey": "test",
|
||||
"NodeID": 33,
|
||||
"Timeout": 30,
|
||||
"RuleListPath": ""
|
||||
},
|
||||
"Options": {
|
||||
"Core": "sing",
|
||||
"EnableProxyProtocol": true,
|
||||
"EnableTFO": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"Core": "xray",
|
||||
"ApiHost": "http://127.0.0.1",
|
||||
"ApiKey": "test",
|
||||
"NodeID": 33,
|
||||
"NodeType": "shadowsocks",
|
||||
"Timeout": 30,
|
||||
"RuleListPath": "",
|
||||
"ListenIP": "0.0.0.0",
|
||||
"SendIP": "0.0.0.0",
|
||||
"EnableProxyProtocol": true,
|
||||
"EnableTFO": true
|
||||
}*/
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user