geodata.go 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. package geodata
  2. import (
  3. "strings"
  4. "github.com/v2fly/v2ray-core/v4/app/router"
  5. )
  6. type loader struct {
  7. LoaderImplementation
  8. }
  9. func (l *loader) LoadGeosite(list string) ([]*router.Domain, error) {
  10. return l.LoadGeositeWithAttr("geosite.dat", list)
  11. }
  12. func (l *loader) LoadGeositeWithAttr(file string, siteWithAttr string) ([]*router.Domain, error) {
  13. parts := strings.Split(siteWithAttr, "@")
  14. if len(parts) == 0 {
  15. return nil, newError("empty rule")
  16. }
  17. list := strings.TrimSpace(parts[0])
  18. attrVal := parts[1:]
  19. if len(list) == 0 {
  20. return nil, newError("empty listname in rule: ", siteWithAttr)
  21. }
  22. domains, err := l.LoadSite(file, list)
  23. if err != nil {
  24. return nil, err
  25. }
  26. attrs := parseAttrs(attrVal)
  27. if attrs.IsEmpty() {
  28. if strings.Contains(siteWithAttr, "@") {
  29. newError("empty attribute list: ", siteWithAttr)
  30. }
  31. return domains, nil
  32. }
  33. filteredDomains := make([]*router.Domain, 0, len(domains))
  34. hasAttrMatched := false
  35. for _, domain := range domains {
  36. if attrs.Match(domain) {
  37. hasAttrMatched = true
  38. filteredDomains = append(filteredDomains, domain)
  39. }
  40. }
  41. if !hasAttrMatched {
  42. newError("attribute match no rule: geosite:", siteWithAttr)
  43. }
  44. return filteredDomains, nil
  45. }
  46. func (l *loader) LoadGeoIP(country string) ([]*router.CIDR, error) {
  47. return l.LoadIP("geoip.dat", country)
  48. }
  49. var loaders map[string]func() LoaderImplementation
  50. func RegisterGeoDataLoaderImplementationCreator(name string, loader func() LoaderImplementation) {
  51. if loaders == nil {
  52. loaders = map[string]func() LoaderImplementation{}
  53. }
  54. loaders[name] = loader
  55. }
  56. func getGeoDataLoaderImplementation(name string) (LoaderImplementation, error) {
  57. if geoLoader, ok := loaders[name]; ok {
  58. return geoLoader(), nil
  59. }
  60. return nil, newError("unable to locate GeoData loader ", name)
  61. }
  62. func GetGeoDataLoader(name string) (Loader, error) {
  63. loadImpl, err := getGeoDataLoaderImplementation(name)
  64. if err == nil {
  65. return &loader{loadImpl}, nil
  66. }
  67. return nil, err
  68. }