2023-01-28 00:50:21 +07:00
/ *
* SPDX - License - Identifier : AGPL - 3.0 - only
2024-01-04 16:28:16 +07:00
* Copyright ( c ) 2022 - 2024 , daeuniverse Organization < dae @ 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"
"reflect"
"time"
2023-04-23 12:27:29 +07:00
"github.com/daeuniverse/dae/pkg/config_parser"
2023-01-28 00:50:21 +07:00
)
2023-07-23 22:52:27 +07:00
var (
Version string
)
2023-01-28 00:50:21 +07:00
type Global struct {
2023-06-04 10:38:05 +07:00
TproxyPort uint16 ` mapstructure:"tproxy_port" default:"12345" `
TproxyPortProtect bool ` mapstructure:"tproxy_port_protect" default:"true" `
SoMarkFromDae uint32 ` mapstructure:"so_mark_from_dae" `
LogLevel string ` mapstructure:"log_level" default:"info" `
2023-02-12 14:39:00 +07:00
// 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-04-29 00:08:46 +07:00
TcpCheckUrl [ ] string ` mapstructure:"tcp_check_url" default:"http://cp.cloudflare.com,1.1.1.1,2606:4700:4700::1111" `
2023-06-11 11:47:30 +07:00
TcpCheckHttpMethod string ` mapstructure:"tcp_check_http_method" default:"HEAD" ` // Use 'HEAD' because some server implementations bypass accounting for this kind of traffic.
2023-04-29 00:08:46 +07:00
UdpCheckDns [ ] string ` mapstructure:"udp_check_dns" default:"dns.google.com:53,8.8.8.8,2001:4860:4860::8888" `
2023-03-25 16:16:24 +07:00
CheckInterval time . Duration ` mapstructure:"check_interval" default:"30s" `
CheckTolerance time . Duration ` mapstructure:"check_tolerance" default:"0" `
LanInterface [ ] string ` mapstructure:"lan_interface" `
WanInterface [ ] string ` mapstructure:"wan_interface" `
AllowInsecure bool ` mapstructure:"allow_insecure" default:"false" `
DialMode string ` mapstructure:"dial_mode" default:"domain" `
DisableWaitingNetwork bool ` mapstructure:"disable_waiting_network" default:"false" `
AutoConfigKernelParameter bool ` mapstructure:"auto_config_kernel_parameter" default:"false" `
2024-03-01 17:27:02 +07:00
// DEPRECATED: not used as of https://github.com/daeuniverse/dae/pull/458
AutoConfigFirewallRule bool ` mapstructure:"auto_config_firewall_rule" default:"false" `
SniffingTimeout time . Duration ` mapstructure:"sniffing_timeout" default:"100ms" `
TlsImplementation string ` mapstructure:"tls_implementation" default:"tls" `
UtlsImitate string ` mapstructure:"utls_imitate" default:"chrome_auto" `
2023-05-27 09:52:13 +07:00
}
type Utls struct {
Imitate string ` mapstructure:"imitate" `
2023-01-28 00:50:21 +07:00
}
2023-02-25 01:38:21 +07:00
type FunctionOrString interface { }
func FunctionOrStringToFunction ( fs FunctionOrString ) ( f * config_parser . Function ) {
switch fs := fs . ( type ) {
case string :
return & config_parser . Function { Name : fs }
case * config_parser . Function :
return fs
2024-04-08 21:29:04 +07:00
case [ ] * config_parser . Function :
if len ( fs ) == 1 {
return fs [ 0 ]
} else {
panic ( fmt . Sprintf ( "unknown type of 'fallback' in section routing: %T" , fs ) )
}
2023-02-25 01:38:21 +07:00
default :
panic ( fmt . Sprintf ( "unknown type of 'fallback' in section routing: %T" , fs ) )
}
2023-01-27 01:10:27 +07:00
}
2023-01-28 00:50:21 +07:00
2023-02-25 21:53:18 +07:00
type FunctionListOrString interface { }
2023-03-01 10:36:08 +07:00
func FunctionListOrStringToFunctionList ( fs FunctionListOrString ) ( f [ ] * config_parser . Function ) {
2023-02-25 21:53:18 +07:00
switch fs := fs . ( type ) {
case string :
return [ ] * config_parser . Function { { Name : fs } }
case [ ] * config_parser . Function :
return fs
default :
panic ( fmt . Sprintf ( "unknown type of 'fallback' in section routing: %T" , fs ) )
}
}
2023-02-25 01:38:21 +07:00
type Group struct {
Name string ` mapstructure:"_" `
2023-07-10 18:44:56 +07:00
Filter [ ] [ ] * config_parser . Function ` mapstructure:"filter" repeatable:"" `
FilterAnnotation [ ] [ ] * config_parser . Param ` mapstructure:"_" `
Policy FunctionListOrString ` mapstructure:"policy" required:"" `
2023-01-27 01:10:27 +07:00
}
2023-01-28 00:50:21 +07:00
2023-02-25 01:38:21 +07:00
type DnsRequestRouting struct {
Rules [ ] * config_parser . RoutingRule ` mapstructure:"_" `
Fallback FunctionOrString ` mapstructure:"fallback" required:"" `
}
type DnsResponseRouting struct {
Rules [ ] * config_parser . RoutingRule ` mapstructure:"_" `
Fallback FunctionOrString ` mapstructure:"fallback" required:"" `
}
2023-02-25 21:53:18 +07:00
type DnsRouting struct {
Request DnsRequestRouting ` mapstructure:"request" `
Response DnsResponseRouting ` mapstructure:"response" `
}
type KeyableString string
2023-02-25 01:38:21 +07:00
type Dns struct {
2023-04-07 22:06:04 +07:00
IpVersionPrefer int ` mapstructure:"ipversion_prefer" `
2023-05-30 21:10:32 +07:00
FixedDomainTtl [ ] KeyableString ` mapstructure:"fixed_domain_ttl" `
2023-04-07 22:06:04 +07:00
Upstream [ ] KeyableString ` mapstructure:"upstream" `
Routing DnsRouting ` mapstructure:"routing" `
2023-02-25 01:38:21 +07:00
}
2023-01-28 00:50:21 +07:00
type Routing struct {
2023-02-18 02:01:51 +07:00
Rules [ ] * config_parser . RoutingRule ` mapstructure:"_" `
2023-03-03 09:59:31 +07:00
Fallback FunctionOrString ` mapstructure:"fallback" default:"direct" `
2023-01-27 01:10:27 +07:00
}
2023-01-28 00:50:21 +07:00
2023-02-25 21:53:18 +07:00
type Config struct {
Global Global ` mapstructure:"global" required:"" desc:"GlobalDesc" `
Subscription [ ] KeyableString ` mapstructure:"subscription" `
Node [ ] KeyableString ` mapstructure:"node" `
2023-03-03 09:59:31 +07:00
Group [ ] Group ` mapstructure:"group" desc:"GroupDesc" `
2023-02-25 21:53:18 +07:00
Routing Routing ` mapstructure:"routing" required:"" `
Dns Dns ` mapstructure:"dns" desc:"DnsDesc" `
2023-01-28 00:50:21 +07:00
}
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-02-25 21:53:18 +07:00
func New ( sections [ ] * config_parser . Section ) ( conf * Config , err error ) {
2023-01-28 00:50:21 +07:00
// 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-02-25 21:53:18 +07:00
conf = & Config { }
2023-01-28 00:50:21 +07:00
// Use specified parser to parse corresponding section.
2023-02-25 21:53:18 +07:00
_val := reflect . ValueOf ( conf )
2023-01-28 00:50:21 +07:00
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 {
2023-02-25 01:38:21 +07:00
if _ , required := structField . Tag . Lookup ( "required" ) ; required {
return nil , fmt . Errorf ( "section %v is required but not provided" , sectionName )
} else {
continue
}
2023-01-28 00:50:21 +07:00
}
// Parse section and unmarshal to field.
2023-02-25 01:38:21 +07:00
if err := SectionParser ( 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 )
}
}
2023-02-18 02:01:51 +07:00
// Apply config patches.
for _ , patch := range patches {
2023-02-25 21:53:18 +07:00
if err = patch ( conf ) ; err != nil {
2023-02-18 02:01:51 +07:00
return nil , err
}
}
2023-02-25 21:53:18 +07:00
return conf , nil
2023-01-28 00:50:21 +07:00
}