2019-02-12 19:54:00 +00:00
|
|
|
package config
|
|
|
|
|
|
|
|
import (
|
2019-02-23 15:29:48 +00:00
|
|
|
"errors"
|
2019-02-12 19:54:00 +00:00
|
|
|
"github.com/cnlh/nps/lib/common"
|
|
|
|
"github.com/cnlh/nps/lib/file"
|
|
|
|
"regexp"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
type CommonConfig struct {
|
|
|
|
Server string
|
|
|
|
VKey string
|
|
|
|
Tp string //bridgeType kcp or tcp
|
|
|
|
AutoReconnection bool
|
|
|
|
Cnf *file.Config
|
2019-02-16 12:43:26 +00:00
|
|
|
ProxyUrl string
|
2019-02-23 15:29:48 +00:00
|
|
|
Client *file.Client
|
|
|
|
}
|
|
|
|
type LocalServer struct {
|
2019-02-26 14:40:28 +00:00
|
|
|
Type string
|
2019-02-23 15:29:48 +00:00
|
|
|
Port int
|
2019-03-26 15:34:55 +00:00
|
|
|
Ip string
|
2019-02-23 15:29:48 +00:00
|
|
|
Password string
|
2019-03-01 09:23:14 +00:00
|
|
|
Target string
|
2019-02-12 19:54:00 +00:00
|
|
|
}
|
|
|
|
type Config struct {
|
|
|
|
content string
|
|
|
|
title []string
|
|
|
|
CommonConfig *CommonConfig
|
|
|
|
Hosts []*file.Host
|
|
|
|
Tasks []*file.Tunnel
|
2019-03-15 06:03:49 +00:00
|
|
|
Healths []*file.Health
|
2019-02-23 15:29:48 +00:00
|
|
|
LocalServer []*LocalServer
|
2019-02-12 19:54:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewConfig(path string) (c *Config, err error) {
|
|
|
|
c = new(Config)
|
|
|
|
var b []byte
|
|
|
|
if b, err = common.ReadAllFromFile(path); err != nil {
|
|
|
|
return
|
|
|
|
} else {
|
2019-03-07 10:07:53 +00:00
|
|
|
if c.content, err = common.ParseStr(string(b)); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2019-02-12 19:54:00 +00:00
|
|
|
if c.title, err = getAllTitle(c.content); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
var nowIndex int
|
|
|
|
var nextIndex int
|
|
|
|
var nowContent string
|
|
|
|
for i := 0; i < len(c.title); i++ {
|
|
|
|
nowIndex = strings.Index(c.content, c.title[i]) + len(c.title[i])
|
|
|
|
if i < len(c.title)-1 {
|
|
|
|
nextIndex = strings.Index(c.content, c.title[i+1])
|
|
|
|
} else {
|
|
|
|
nextIndex = len(c.content)
|
|
|
|
}
|
|
|
|
nowContent = c.content[nowIndex:nextIndex]
|
2019-02-23 15:29:48 +00:00
|
|
|
|
2019-03-15 06:03:49 +00:00
|
|
|
if strings.Index(getTitleContent(c.title[i]), "secret") == 0 && !strings.Contains(nowContent, "mode") {
|
2019-02-26 14:40:28 +00:00
|
|
|
local := delLocalService(nowContent)
|
|
|
|
local.Type = "secret"
|
|
|
|
c.LocalServer = append(c.LocalServer, local)
|
|
|
|
continue
|
|
|
|
}
|
2019-03-15 06:03:49 +00:00
|
|
|
//except mode
|
|
|
|
if strings.Index(getTitleContent(c.title[i]), "p2p") == 0 && !strings.Contains(nowContent, "mode") {
|
2019-02-26 14:40:28 +00:00
|
|
|
local := delLocalService(nowContent)
|
|
|
|
local.Type = "p2p"
|
|
|
|
c.LocalServer = append(c.LocalServer, local)
|
2019-02-23 15:29:48 +00:00
|
|
|
continue
|
|
|
|
}
|
2019-03-15 06:03:49 +00:00
|
|
|
//health set
|
|
|
|
if strings.Index(getTitleContent(c.title[i]), "health") == 0 {
|
|
|
|
c.Healths = append(c.Healths, dealHealth(nowContent))
|
|
|
|
continue
|
|
|
|
}
|
2019-02-12 19:54:00 +00:00
|
|
|
switch c.title[i] {
|
|
|
|
case "[common]":
|
|
|
|
c.CommonConfig = dealCommon(nowContent)
|
|
|
|
default:
|
|
|
|
if strings.Index(nowContent, "host") > -1 {
|
|
|
|
h := dealHost(nowContent)
|
|
|
|
h.Remark = getTitleContent(c.title[i])
|
|
|
|
c.Hosts = append(c.Hosts, h)
|
|
|
|
} else {
|
|
|
|
t := dealTunnel(nowContent)
|
|
|
|
t.Remark = getTitleContent(c.title[i])
|
|
|
|
c.Tasks = append(c.Tasks, t)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func getTitleContent(s string) string {
|
|
|
|
re, _ := regexp.Compile(`[\[\]]`)
|
|
|
|
return re.ReplaceAllString(s, "")
|
|
|
|
}
|
2019-02-23 15:29:48 +00:00
|
|
|
|
2019-02-12 19:54:00 +00:00
|
|
|
func dealCommon(s string) *CommonConfig {
|
|
|
|
c := &CommonConfig{}
|
|
|
|
c.Cnf = new(file.Config)
|
2019-02-23 15:29:48 +00:00
|
|
|
c.Client = file.NewClient("", true, true)
|
2019-03-24 01:54:56 +00:00
|
|
|
for _, v := range splitStr(s) {
|
2019-02-12 19:54:00 +00:00
|
|
|
item := strings.Split(v, "=")
|
|
|
|
if len(item) == 0 {
|
|
|
|
continue
|
|
|
|
} else if len(item) == 1 {
|
|
|
|
item = append(item, "")
|
|
|
|
}
|
|
|
|
switch item[0] {
|
2019-03-26 15:34:55 +00:00
|
|
|
case "server_addr":
|
2019-02-12 19:54:00 +00:00
|
|
|
c.Server = item[1]
|
|
|
|
case "vkey":
|
|
|
|
c.VKey = item[1]
|
2019-03-26 15:34:55 +00:00
|
|
|
case "conn_type":
|
2019-02-12 19:54:00 +00:00
|
|
|
c.Tp = item[1]
|
|
|
|
case "auto_reconnection":
|
|
|
|
c.AutoReconnection = common.GetBoolByStr(item[1])
|
|
|
|
case "username":
|
|
|
|
c.Cnf.U = item[1]
|
|
|
|
case "password":
|
|
|
|
c.Cnf.P = item[1]
|
|
|
|
case "compress":
|
2019-03-01 09:23:14 +00:00
|
|
|
c.Cnf.Compress = common.GetBoolByStr(item[1])
|
2019-02-12 19:54:00 +00:00
|
|
|
case "crypt":
|
|
|
|
c.Cnf.Crypt = common.GetBoolByStr(item[1])
|
2019-02-16 12:43:26 +00:00
|
|
|
case "proxy_socks5_url":
|
|
|
|
c.ProxyUrl = item[1]
|
2019-02-23 15:29:48 +00:00
|
|
|
case "rate_limit":
|
|
|
|
c.Client.RateLimit = common.GetIntNoErrByStr(item[1])
|
|
|
|
case "flow_limit":
|
|
|
|
c.Client.Flow.FlowLimit = int64(common.GetIntNoErrByStr(item[1]))
|
|
|
|
case "max_conn":
|
|
|
|
c.Client.MaxConn = common.GetIntNoErrByStr(item[1])
|
|
|
|
case "remark":
|
|
|
|
c.Client.Remark = item[1]
|
2019-02-12 19:54:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return c
|
|
|
|
}
|
2019-02-23 15:29:48 +00:00
|
|
|
|
2019-02-12 19:54:00 +00:00
|
|
|
func dealHost(s string) *file.Host {
|
|
|
|
h := &file.Host{}
|
|
|
|
var headerChange string
|
2019-03-24 01:54:56 +00:00
|
|
|
for _, v := range splitStr(s) {
|
2019-02-12 19:54:00 +00:00
|
|
|
item := strings.Split(v, "=")
|
|
|
|
if len(item) == 0 {
|
|
|
|
continue
|
|
|
|
} else if len(item) == 1 {
|
|
|
|
item = append(item, "")
|
|
|
|
}
|
2019-03-15 06:03:49 +00:00
|
|
|
switch strings.TrimSpace(item[0]) {
|
2019-02-12 19:54:00 +00:00
|
|
|
case "host":
|
|
|
|
h.Host = item[1]
|
2019-03-26 15:34:55 +00:00
|
|
|
case "target_addr":
|
2019-02-12 19:54:00 +00:00
|
|
|
h.Target = strings.Replace(item[1], ",", "\n", -1)
|
|
|
|
case "host_change":
|
|
|
|
h.HostChange = item[1]
|
2019-03-26 15:46:34 +00:00
|
|
|
case "scheme":
|
2019-03-15 06:03:49 +00:00
|
|
|
h.Scheme = item[1]
|
2019-02-16 12:43:26 +00:00
|
|
|
case "location":
|
|
|
|
h.Location = item[1]
|
2019-03-15 06:03:49 +00:00
|
|
|
default:
|
|
|
|
if strings.Contains(item[0], "header") {
|
|
|
|
headerChange += strings.Replace(item[0], "header_", "", -1) + ":" + item[1] + "\n"
|
|
|
|
}
|
|
|
|
h.HeaderChange = headerChange
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return h
|
|
|
|
}
|
|
|
|
|
|
|
|
func dealHealth(s string) *file.Health {
|
|
|
|
h := &file.Health{}
|
2019-03-24 01:54:56 +00:00
|
|
|
for _, v := range splitStr(s) {
|
2019-03-15 06:03:49 +00:00
|
|
|
item := strings.Split(v, "=")
|
|
|
|
if len(item) == 0 {
|
|
|
|
continue
|
|
|
|
} else if len(item) == 1 {
|
|
|
|
item = append(item, "")
|
|
|
|
}
|
|
|
|
switch strings.TrimSpace(item[0]) {
|
2019-03-07 10:07:53 +00:00
|
|
|
case "health_check_timeout":
|
|
|
|
h.HealthCheckTimeout = common.GetIntNoErrByStr(item[1])
|
|
|
|
case "health_check_max_failed":
|
|
|
|
h.HealthMaxFail = common.GetIntNoErrByStr(item[1])
|
|
|
|
case "health_check_interval":
|
|
|
|
h.HealthCheckInterval = common.GetIntNoErrByStr(item[1])
|
|
|
|
case "health_http_url":
|
|
|
|
h.HttpHealthUrl = item[1]
|
2019-03-15 06:03:49 +00:00
|
|
|
case "health_check_type":
|
|
|
|
h.HealthCheckType = item[1]
|
|
|
|
case "health_check_target":
|
|
|
|
h.HealthCheckTarget = item[1]
|
2019-02-12 19:54:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return h
|
|
|
|
}
|
|
|
|
|
|
|
|
func dealTunnel(s string) *file.Tunnel {
|
|
|
|
t := &file.Tunnel{}
|
2019-03-24 01:54:56 +00:00
|
|
|
for _, v := range splitStr(s) {
|
2019-02-12 19:54:00 +00:00
|
|
|
item := strings.Split(v, "=")
|
|
|
|
if len(item) == 0 {
|
|
|
|
continue
|
|
|
|
} else if len(item) == 1 {
|
|
|
|
item = append(item, "")
|
|
|
|
}
|
2019-03-15 06:03:49 +00:00
|
|
|
switch strings.TrimSpace(item[0]) {
|
2019-03-26 15:34:55 +00:00
|
|
|
case "server_port":
|
2019-02-15 14:59:28 +00:00
|
|
|
t.Ports = item[1]
|
2019-03-26 15:34:55 +00:00
|
|
|
case "server_ip":
|
|
|
|
t.ServerIp = item[1]
|
2019-02-12 19:54:00 +00:00
|
|
|
case "mode":
|
|
|
|
t.Mode = item[1]
|
2019-03-26 15:34:55 +00:00
|
|
|
case "target_port", "target_addr":
|
2019-03-07 10:07:53 +00:00
|
|
|
t.Target = strings.Replace(item[1], ",", "\n", -1)
|
2019-03-26 15:34:55 +00:00
|
|
|
case "target_ip":
|
2019-02-23 15:29:48 +00:00
|
|
|
t.TargetAddr = item[1]
|
|
|
|
case "password":
|
|
|
|
t.Password = item[1]
|
2019-03-02 09:43:21 +00:00
|
|
|
case "local_path":
|
|
|
|
t.LocalPath = item[1]
|
|
|
|
case "strip_pre":
|
|
|
|
t.StripPre = item[1]
|
2019-02-12 19:54:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return t
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-02-23 15:29:48 +00:00
|
|
|
func delLocalService(s string) *LocalServer {
|
|
|
|
l := new(LocalServer)
|
2019-03-24 01:54:56 +00:00
|
|
|
for _, v := range splitStr(s) {
|
2019-02-23 15:29:48 +00:00
|
|
|
item := strings.Split(v, "=")
|
|
|
|
if len(item) == 0 {
|
|
|
|
continue
|
|
|
|
} else if len(item) == 1 {
|
|
|
|
item = append(item, "")
|
|
|
|
}
|
|
|
|
switch item[0] {
|
2019-03-26 15:34:55 +00:00
|
|
|
case "local_port":
|
2019-02-23 15:29:48 +00:00
|
|
|
l.Port = common.GetIntNoErrByStr(item[1])
|
2019-03-26 15:34:55 +00:00
|
|
|
case "local_ip":
|
|
|
|
l.Ip = item[1]
|
2019-02-23 15:29:48 +00:00
|
|
|
case "password":
|
|
|
|
l.Password = item[1]
|
2019-03-26 15:34:55 +00:00
|
|
|
case "target_addr":
|
2019-03-01 09:23:14 +00:00
|
|
|
l.Target = item[1]
|
2019-02-23 15:29:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return l
|
|
|
|
}
|
|
|
|
|
2019-02-12 19:54:00 +00:00
|
|
|
func getAllTitle(content string) (arr []string, err error) {
|
|
|
|
var re *regexp.Regexp
|
|
|
|
re, err = regexp.Compile(`\[.+?\]`)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
arr = re.FindAllString(content, -1)
|
2019-02-23 15:29:48 +00:00
|
|
|
m := make(map[string]bool)
|
|
|
|
for _, v := range arr {
|
|
|
|
if _, ok := m[v]; ok {
|
|
|
|
err = errors.New("Item names are not allowed to be duplicated")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
m[v] = true
|
|
|
|
}
|
2019-02-12 19:54:00 +00:00
|
|
|
return
|
|
|
|
}
|
2019-03-24 01:54:56 +00:00
|
|
|
|
|
|
|
func splitStr(s string) (configDataArr []string) {
|
|
|
|
if common.IsWindows() {
|
|
|
|
configDataArr = strings.Split(s, "\r\n")
|
|
|
|
}
|
|
|
|
if len(configDataArr) < 3 {
|
|
|
|
configDataArr = strings.Split(s, "\n")
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|