github.com/sagernet/sing-box@v1.2.7/option/route.go (about) 1 package option 2 3 import ( 4 "reflect" 5 6 "github.com/sagernet/sing-box/common/json" 7 C "github.com/sagernet/sing-box/constant" 8 "github.com/sagernet/sing/common" 9 E "github.com/sagernet/sing/common/exceptions" 10 ) 11 12 type RouteOptions struct { 13 GeoIP *GeoIPOptions `json:"geoip,omitempty"` 14 Geosite *GeositeOptions `json:"geosite,omitempty"` 15 Rules []Rule `json:"rules,omitempty"` 16 Final string `json:"final,omitempty"` 17 FindProcess bool `json:"find_process,omitempty"` 18 AutoDetectInterface bool `json:"auto_detect_interface,omitempty"` 19 OverrideAndroidVPN bool `json:"override_android_vpn,omitempty"` 20 DefaultInterface string `json:"default_interface,omitempty"` 21 DefaultMark int `json:"default_mark,omitempty"` 22 } 23 24 type GeoIPOptions struct { 25 Path string `json:"path,omitempty"` 26 DownloadURL string `json:"download_url,omitempty"` 27 DownloadDetour string `json:"download_detour,omitempty"` 28 } 29 30 type GeositeOptions struct { 31 Path string `json:"path,omitempty"` 32 DownloadURL string `json:"download_url,omitempty"` 33 DownloadDetour string `json:"download_detour,omitempty"` 34 } 35 36 type _Rule struct { 37 Type string `json:"type,omitempty"` 38 DefaultOptions DefaultRule `json:"-"` 39 LogicalOptions LogicalRule `json:"-"` 40 } 41 42 type Rule _Rule 43 44 func (r Rule) MarshalJSON() ([]byte, error) { 45 var v any 46 switch r.Type { 47 case C.RuleTypeDefault: 48 r.Type = "" 49 v = r.DefaultOptions 50 case C.RuleTypeLogical: 51 v = r.LogicalOptions 52 default: 53 return nil, E.New("unknown rule type: " + r.Type) 54 } 55 return MarshallObjects((_Rule)(r), v) 56 } 57 58 func (r *Rule) UnmarshalJSON(bytes []byte) error { 59 err := json.Unmarshal(bytes, (*_Rule)(r)) 60 if err != nil { 61 return err 62 } 63 var v any 64 switch r.Type { 65 case "", C.RuleTypeDefault: 66 r.Type = C.RuleTypeDefault 67 v = &r.DefaultOptions 68 case C.RuleTypeLogical: 69 v = &r.LogicalOptions 70 default: 71 return E.New("unknown rule type: " + r.Type) 72 } 73 err = UnmarshallExcluded(bytes, (*_Rule)(r), v) 74 if err != nil { 75 return E.Cause(err, "route rule") 76 } 77 return nil 78 } 79 80 type DefaultRule struct { 81 Inbound Listable[string] `json:"inbound,omitempty"` 82 IPVersion int `json:"ip_version,omitempty"` 83 Network string `json:"network,omitempty"` 84 AuthUser Listable[string] `json:"auth_user,omitempty"` 85 Protocol Listable[string] `json:"protocol,omitempty"` 86 Domain Listable[string] `json:"domain,omitempty"` 87 DomainSuffix Listable[string] `json:"domain_suffix,omitempty"` 88 DomainKeyword Listable[string] `json:"domain_keyword,omitempty"` 89 DomainRegex Listable[string] `json:"domain_regex,omitempty"` 90 Geosite Listable[string] `json:"geosite,omitempty"` 91 SourceGeoIP Listable[string] `json:"source_geoip,omitempty"` 92 GeoIP Listable[string] `json:"geoip,omitempty"` 93 SourceIPCIDR Listable[string] `json:"source_ip_cidr,omitempty"` 94 IPCIDR Listable[string] `json:"ip_cidr,omitempty"` 95 SourcePort Listable[uint16] `json:"source_port,omitempty"` 96 SourcePortRange Listable[string] `json:"source_port_range,omitempty"` 97 Port Listable[uint16] `json:"port,omitempty"` 98 PortRange Listable[string] `json:"port_range,omitempty"` 99 ProcessName Listable[string] `json:"process_name,omitempty"` 100 ProcessPath Listable[string] `json:"process_path,omitempty"` 101 PackageName Listable[string] `json:"package_name,omitempty"` 102 User Listable[string] `json:"user,omitempty"` 103 UserID Listable[int32] `json:"user_id,omitempty"` 104 ClashMode string `json:"clash_mode,omitempty"` 105 Invert bool `json:"invert,omitempty"` 106 Outbound string `json:"outbound,omitempty"` 107 } 108 109 func (r DefaultRule) IsValid() bool { 110 var defaultValue DefaultRule 111 defaultValue.Invert = r.Invert 112 defaultValue.Outbound = r.Outbound 113 return !reflect.DeepEqual(r, defaultValue) 114 } 115 116 type LogicalRule struct { 117 Mode string `json:"mode"` 118 Rules []DefaultRule `json:"rules,omitempty"` 119 Invert bool `json:"invert,omitempty"` 120 Outbound string `json:"outbound,omitempty"` 121 } 122 123 func (r LogicalRule) IsValid() bool { 124 return len(r.Rules) > 0 && common.All(r.Rules, DefaultRule.IsValid) 125 }