dae/config/config.go

115 lines
4.0 KiB
Go
Raw Normal View History

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"
"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 {
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"`
UdpCheckDns string `mapstructure:"udp_check_dns" default:"dns.google:53"`
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:""`
LanInterface []string `mapstructure:"lan_interface"`
2023-02-18 01:06:23 +07:00
LanNatDirect bool `mapstructure:"lan_nat_direct" default:"true"`
WanInterface []string `mapstructure:"wan_interface"`
AllowInsecure bool `mapstructure:"allow_insecure" default:"false"`
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)
}
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.
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
}