github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/infra/conf/geodata/geodata.go (about)

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