host.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. package resolver
  2. import (
  3. "errors"
  4. "net/netip"
  5. "os"
  6. "strconv"
  7. "strings"
  8. _ "unsafe"
  9. "github.com/metacubex/mihomo/common/utils"
  10. "github.com/metacubex/mihomo/component/resolver/hosts"
  11. "github.com/metacubex/mihomo/component/trie"
  12. "github.com/metacubex/randv2"
  13. )
  14. var (
  15. DisableSystemHosts, _ = strconv.ParseBool(os.Getenv("DISABLE_SYSTEM_HOSTS"))
  16. UseSystemHosts bool
  17. )
  18. type Hosts struct {
  19. *trie.DomainTrie[HostValue]
  20. }
  21. func NewHosts(hosts *trie.DomainTrie[HostValue]) Hosts {
  22. return Hosts{
  23. hosts,
  24. }
  25. }
  26. // Return the search result and whether to match the parameter `isDomain`
  27. func (h *Hosts) Search(domain string, isDomain bool) (*HostValue, bool) {
  28. if value := h.DomainTrie.Search(domain); value != nil {
  29. hostValue := value.Data()
  30. for {
  31. if isDomain && hostValue.IsDomain {
  32. return &hostValue, true
  33. } else {
  34. if node := h.DomainTrie.Search(hostValue.Domain); node != nil {
  35. hostValue = node.Data()
  36. } else {
  37. break
  38. }
  39. }
  40. }
  41. if isDomain == hostValue.IsDomain {
  42. return &hostValue, true
  43. }
  44. return &hostValue, false
  45. }
  46. if !isDomain && !DisableSystemHosts && UseSystemHosts {
  47. addr, _ := hosts.LookupStaticHost(domain)
  48. if hostValue, err := NewHostValue(addr); err == nil {
  49. return &hostValue, true
  50. }
  51. }
  52. return nil, false
  53. }
  54. type HostValue struct {
  55. IsDomain bool
  56. IPs []netip.Addr
  57. Domain string
  58. }
  59. func NewHostValue(value any) (HostValue, error) {
  60. isDomain := true
  61. ips := make([]netip.Addr, 0)
  62. domain := ""
  63. if valueArr, err := utils.ToStringSlice(value); err != nil {
  64. return HostValue{}, err
  65. } else {
  66. if len(valueArr) > 1 {
  67. isDomain = false
  68. for _, str := range valueArr {
  69. if ip, err := netip.ParseAddr(str); err == nil {
  70. ips = append(ips, ip)
  71. } else {
  72. return HostValue{}, err
  73. }
  74. }
  75. } else if len(valueArr) == 1 {
  76. host := valueArr[0]
  77. if ip, err := netip.ParseAddr(host); err == nil {
  78. ips = append(ips, ip)
  79. isDomain = false
  80. } else {
  81. domain = host
  82. }
  83. }
  84. }
  85. if isDomain {
  86. return NewHostValueByDomain(domain)
  87. } else {
  88. return NewHostValueByIPs(ips)
  89. }
  90. }
  91. func NewHostValueByIPs(ips []netip.Addr) (HostValue, error) {
  92. if len(ips) == 0 {
  93. return HostValue{}, errors.New("ip list is empty")
  94. }
  95. return HostValue{
  96. IsDomain: false,
  97. IPs: ips,
  98. }, nil
  99. }
  100. func NewHostValueByDomain(domain string) (HostValue, error) {
  101. domain = strings.Trim(domain, ".")
  102. item := strings.Split(domain, ".")
  103. if len(item) < 2 {
  104. return HostValue{}, errors.New("invaild domain")
  105. }
  106. return HostValue{
  107. IsDomain: true,
  108. Domain: domain,
  109. }, nil
  110. }
  111. func (hv HostValue) RandIP() (netip.Addr, error) {
  112. if hv.IsDomain {
  113. return netip.Addr{}, errors.New("value type is error")
  114. }
  115. return hv.IPs[randv2.IntN(len(hv.IPs))], nil
  116. }