route.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. package option
  2. import (
  3. "encoding/json"
  4. C "github.com/sagernet/sing-box/constant"
  5. "github.com/sagernet/sing/common"
  6. E "github.com/sagernet/sing/common/exceptions"
  7. )
  8. type RouteOptions struct {
  9. GeoIP *GeoIPOptions `json:"geoip,omitempty"`
  10. Rules []Rule `json:"rules,omitempty"`
  11. }
  12. func (o RouteOptions) Equals(other RouteOptions) bool {
  13. return common.ComparablePtrEquals(o.GeoIP, other.GeoIP) &&
  14. common.SliceEquals(o.Rules, other.Rules)
  15. }
  16. type GeoIPOptions struct {
  17. Path string `json:"path,omitempty"`
  18. DownloadURL string `json:"download_url,omitempty"`
  19. DownloadDetour string `json:"download_detour,omitempty"`
  20. }
  21. type _Rule struct {
  22. Type string `json:"type,omitempty"`
  23. DefaultOptions *DefaultRule `json:"-"`
  24. LogicalOptions *LogicalRule `json:"-"`
  25. }
  26. type Rule _Rule
  27. func (r Rule) Equals(other Rule) bool {
  28. return r.Type == other.Type &&
  29. common.PtrEquals(r.DefaultOptions, other.DefaultOptions) &&
  30. common.PtrEquals(r.LogicalOptions, other.LogicalOptions)
  31. }
  32. func (r Rule) MarshalJSON() ([]byte, error) {
  33. var v any
  34. switch r.Type {
  35. case C.RuleTypeDefault:
  36. v = r.DefaultOptions
  37. case C.RuleTypeLogical:
  38. v = r.LogicalOptions
  39. default:
  40. return nil, E.New("unknown rule type: " + r.Type)
  41. }
  42. return MarshallObjects((_Rule)(r), v)
  43. }
  44. func (r *Rule) UnmarshalJSON(bytes []byte) error {
  45. err := json.Unmarshal(bytes, (*_Rule)(r))
  46. if err != nil {
  47. return err
  48. }
  49. if r.Type == "" {
  50. r.Type = C.RuleTypeDefault
  51. }
  52. var v any
  53. switch r.Type {
  54. case C.RuleTypeDefault:
  55. v = &r.DefaultOptions
  56. case C.RuleTypeLogical:
  57. v = &r.LogicalOptions
  58. default:
  59. return E.New("unknown rule type: " + r.Type)
  60. }
  61. return json.Unmarshal(bytes, v)
  62. }
  63. type DefaultRule struct {
  64. Inbound Listable[string] `json:"inbound,omitempty"`
  65. IPVersion int `json:"ip_version,omitempty"`
  66. Network string `json:"network,omitempty"`
  67. Protocol Listable[string] `json:"protocol,omitempty"`
  68. Domain Listable[string] `json:"domain,omitempty"`
  69. DomainSuffix Listable[string] `json:"domain_suffix,omitempty"`
  70. DomainKeyword Listable[string] `json:"domain_keyword,omitempty"`
  71. SourceGeoIP Listable[string] `json:"source_geoip,omitempty"`
  72. GeoIP Listable[string] `json:"geoip,omitempty"`
  73. SourceIPCIDR Listable[string] `json:"source_ip_cidr,omitempty"`
  74. IPCIDR Listable[string] `json:"ip_cidr,omitempty"`
  75. SourcePort Listable[uint16] `json:"source_port,omitempty"`
  76. Port Listable[uint16] `json:"port,omitempty"`
  77. // ProcessName Listable[string] `json:"process_name,omitempty"`
  78. // ProcessPath Listable[string] `json:"process_path,omitempty"`
  79. Outbound string `json:"outbound,omitempty"`
  80. }
  81. func (r DefaultRule) IsValid() bool {
  82. var defaultValue DefaultRule
  83. defaultValue.Outbound = r.Outbound
  84. return !r.Equals(defaultValue)
  85. }
  86. func (r DefaultRule) Equals(other DefaultRule) bool {
  87. return common.ComparableSliceEquals(r.Inbound, other.Inbound) &&
  88. r.IPVersion == other.IPVersion &&
  89. r.Network == other.Network &&
  90. common.ComparableSliceEquals(r.Protocol, other.Protocol) &&
  91. common.ComparableSliceEquals(r.Domain, other.Domain) &&
  92. common.ComparableSliceEquals(r.DomainSuffix, other.DomainSuffix) &&
  93. common.ComparableSliceEquals(r.DomainKeyword, other.DomainKeyword) &&
  94. common.ComparableSliceEquals(r.SourceGeoIP, other.SourceGeoIP) &&
  95. common.ComparableSliceEquals(r.GeoIP, other.GeoIP) &&
  96. common.ComparableSliceEquals(r.SourceIPCIDR, other.SourceIPCIDR) &&
  97. common.ComparableSliceEquals(r.IPCIDR, other.IPCIDR) &&
  98. common.ComparableSliceEquals(r.SourcePort, other.SourcePort) &&
  99. common.ComparableSliceEquals(r.Port, other.Port) &&
  100. r.Outbound == other.Outbound
  101. }
  102. type LogicalRule struct {
  103. Mode string `json:"mode"`
  104. Rules []DefaultRule `json:"rules,omitempty"`
  105. Outbound string `json:"outbound,omitempty"`
  106. }
  107. func (r LogicalRule) IsValid() bool {
  108. return len(r.Rules) > 0 && common.All(r.Rules, DefaultRule.IsValid)
  109. }
  110. func (r LogicalRule) Equals(other LogicalRule) bool {
  111. return r.Mode == other.Mode &&
  112. common.SliceEquals(r.Rules, other.Rules) &&
  113. r.Outbound == other.Outbound
  114. }