2023-01-28 00:50:21 +07:00
|
|
|
/*
|
|
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
2023-01-28 12:56:06 +07:00
|
|
|
* Copyright (c) since 2023, v2rayA Organization <team@v2raya.org>
|
2023-01-28 00:50:21 +07:00
|
|
|
*/
|
|
|
|
|
2023-01-27 01:10:27 +07:00
|
|
|
package config
|
|
|
|
|
2023-01-28 00:50:21 +07:00
|
|
|
import (
|
|
|
|
"fmt"
|
2023-02-08 19:15:24 +07:00
|
|
|
"github.com/v2rayA/dae/common"
|
2023-01-28 00:50:21 +07:00
|
|
|
"github.com/v2rayA/dae/pkg/config_parser"
|
|
|
|
"reflect"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Global struct {
|
2023-02-12 14:39:00 +07:00
|
|
|
TproxyPort uint16 `mapstructure:"tproxy_port" default:"12345"`
|
|
|
|
LogLevel string `mapstructure:"log_level" default:"info"`
|
|
|
|
// We use DirectTcpCheckUrl to check (tcp)*(ipv4/ipv6) connectivity for direct.
|
|
|
|
//DirectTcpCheckUrl string `mapstructure:"direct_tcp_check_url" default:"http://www.qualcomm.cn/generate_204"`
|
2023-02-18 01:06:23 +07:00
|
|
|
TcpCheckUrl string `mapstructure:"tcp_check_url" default:"http://keep-alv.google.com/generate_204"`
|
2023-02-12 14:39:00 +07:00
|
|
|
UdpCheckDns string `mapstructure:"udp_check_dns" default:"dns.google:53"`
|
2023-02-09 20:16:51 +07:00
|
|
|
CheckInterval time.Duration `mapstructure:"check_interval" default:"30s"`
|
|
|
|
CheckTolerance time.Duration `mapstructure:"check_tolerance" default:"0"`
|
2023-02-18 01:06:23 +07:00
|
|
|
DnsUpstream common.UrlOrEmpty `mapstructure:"dns_upstream" default:""`
|
2023-02-09 20:16:51 +07:00
|
|
|
LanInterface []string `mapstructure:"lan_interface"`
|
2023-02-18 01:06:23 +07:00
|
|
|
LanNatDirect bool `mapstructure:"lan_nat_direct" default:"true"`
|
2023-02-09 20:16:51 +07:00
|
|
|
WanInterface []string `mapstructure:"wan_interface"`
|
2023-02-12 16:17:51 +07:00
|
|
|
AllowInsecure bool `mapstructure:"allow_insecure" default:"false"`
|
2023-02-15 00:53:53 +07:00
|
|
|
DialMode string `mapstructure:"dial_mode" default:"domain"`
|
2023-01-28 00:50:21 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
type Group struct {
|
|
|
|
Name string
|
|
|
|
Param GroupParam
|
2023-01-27 01:10:27 +07:00
|
|
|
}
|
2023-01-28 00:50:21 +07:00
|
|
|
|
|
|
|
type GroupParam struct {
|
2023-02-12 10:17:10 +07:00
|
|
|
Filter []*config_parser.Function `mapstructure:"filter"`
|
2023-01-28 00:50:21 +07:00
|
|
|
Policy interface{} `mapstructure:"policy" required:""`
|
2023-01-27 01:10:27 +07:00
|
|
|
}
|
2023-01-28 00:50:21 +07:00
|
|
|
|
|
|
|
type Routing struct {
|
|
|
|
Rules []*config_parser.RoutingRule `mapstructure:"_"`
|
|
|
|
Final string `mapstructure:"final" required:""`
|
2023-01-27 01:10:27 +07:00
|
|
|
}
|
2023-01-28 00:50:21 +07:00
|
|
|
|
2023-01-27 01:10:27 +07:00
|
|
|
type Params struct {
|
2023-01-28 00:50:21 +07:00
|
|
|
Global Global `mapstructure:"global" parser:"ParamParser"`
|
|
|
|
Subscription []string `mapstructure:"subscription" parser:"StringListParser"`
|
|
|
|
Node []string `mapstructure:"node" parser:"StringListParser"`
|
|
|
|
Group []Group `mapstructure:"group" parser:"GroupListParser"`
|
|
|
|
Routing Routing `mapstructure:"routing" parser:"RoutingRuleAndParamParser"`
|
|
|
|
}
|
2023-01-27 01:10:27 +07:00
|
|
|
|
2023-02-09 22:17:49 +07:00
|
|
|
// New params from sections. This func assumes merging (section "include") and deduplication for section names has been executed.
|
2023-01-28 00:50:21 +07:00
|
|
|
func New(sections []*config_parser.Section) (params *Params, err error) {
|
|
|
|
// Set up name to section for further use.
|
|
|
|
type Section struct {
|
|
|
|
Val *config_parser.Section
|
|
|
|
Parsed bool
|
|
|
|
}
|
|
|
|
nameToSection := make(map[string]*Section)
|
|
|
|
for _, section := range sections {
|
|
|
|
nameToSection[section.Name] = &Section{Val: section}
|
|
|
|
}
|
2023-01-27 01:10:27 +07:00
|
|
|
|
2023-01-28 00:50:21 +07:00
|
|
|
params = &Params{}
|
|
|
|
// Use specified parser to parse corresponding section.
|
|
|
|
_val := reflect.ValueOf(params)
|
|
|
|
val := _val.Elem()
|
|
|
|
typ := val.Type()
|
|
|
|
for i := 0; i < val.NumField(); i++ {
|
|
|
|
field := val.Field(i)
|
|
|
|
structField := typ.Field(i)
|
2023-01-27 01:10:27 +07:00
|
|
|
|
2023-01-28 00:50:21 +07:00
|
|
|
// Find corresponding section from sections.
|
|
|
|
sectionName, ok := structField.Tag.Lookup("mapstructure")
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("no mapstructure is specified in field %v", structField.Name)
|
|
|
|
}
|
|
|
|
section, ok := nameToSection[sectionName]
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("section %v is required but not provided", sectionName)
|
|
|
|
}
|
2023-01-27 01:10:27 +07:00
|
|
|
|
2023-01-28 00:50:21 +07:00
|
|
|
// Find corresponding parser func.
|
|
|
|
parserName, ok := structField.Tag.Lookup("parser")
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("no parser is specified in field %v", structField.Name)
|
|
|
|
}
|
2023-02-08 15:07:23 +07:00
|
|
|
parser, ok := ParserMap[parserName]
|
2023-01-28 00:50:21 +07:00
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("unknown parser %v in field %v", parserName, structField.Name)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse section and unmarshal to field.
|
2023-02-08 15:07:23 +07:00
|
|
|
if err := parser(field.Addr(), section.Val); err != nil {
|
2023-01-28 00:50:21 +07:00
|
|
|
return nil, fmt.Errorf("failed to parse \"%v\": %w", sectionName, err)
|
|
|
|
}
|
|
|
|
section.Parsed = true
|
|
|
|
}
|
|
|
|
|
2023-02-09 22:17:49 +07:00
|
|
|
// Report unknown. Not "unused" because we assume section name deduplication has been executed before this func.
|
2023-01-28 00:50:21 +07:00
|
|
|
for name, section := range nameToSection {
|
2023-02-09 22:17:49 +07:00
|
|
|
if section.Val.Name == "include" {
|
|
|
|
continue
|
|
|
|
}
|
2023-01-28 00:50:21 +07:00
|
|
|
if !section.Parsed {
|
|
|
|
return nil, fmt.Errorf("unknown section: %v", name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return params, nil
|
|
|
|
}
|