chore: better geodata shared
This commit is contained in:
parent
7e10d78d53
commit
a7944f1369
3 changed files with 44 additions and 49 deletions
|
@ -1,13 +1,10 @@
|
||||||
package geodata
|
package geodata
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/component/geodata/router"
|
"github.com/Dreamacro/clash/component/geodata/router"
|
||||||
"github.com/Dreamacro/clash/log"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
)
|
)
|
||||||
|
|
||||||
type loader struct {
|
type loader struct {
|
||||||
|
@ -15,47 +12,7 @@ type loader struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *loader) LoadGeoSite(list string) ([]*router.Domain, error) {
|
func (l *loader) LoadGeoSite(list string) ([]*router.Domain, error) {
|
||||||
return l.LoadGeoSiteWithAttr(C.GeositeName, list)
|
return l.LoadSiteByPath(C.GeositeName, list)
|
||||||
}
|
|
||||||
|
|
||||||
func (l *loader) LoadGeoSiteWithAttr(file string, siteWithAttr string) ([]*router.Domain, error) {
|
|
||||||
parts := strings.Split(siteWithAttr, "@")
|
|
||||||
if len(parts) == 0 {
|
|
||||||
return nil, errors.New("empty rule")
|
|
||||||
}
|
|
||||||
list := strings.TrimSpace(parts[0])
|
|
||||||
attrVal := parts[1:]
|
|
||||||
|
|
||||||
if len(list) == 0 {
|
|
||||||
return nil, fmt.Errorf("empty listname in rule: %s", siteWithAttr)
|
|
||||||
}
|
|
||||||
|
|
||||||
domains, err := l.LoadSiteByPath(file, list)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
attrs := parseAttrs(attrVal)
|
|
||||||
if attrs.IsEmpty() {
|
|
||||||
if strings.Contains(siteWithAttr, "@") {
|
|
||||||
log.Warnln("empty attribute list: %s", siteWithAttr)
|
|
||||||
}
|
|
||||||
return domains, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
filteredDomains := make([]*router.Domain, 0, len(domains))
|
|
||||||
hasAttrMatched := false
|
|
||||||
for _, domain := range domains {
|
|
||||||
if attrs.Match(domain) {
|
|
||||||
hasAttrMatched = true
|
|
||||||
filteredDomains = append(filteredDomains, domain)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !hasAttrMatched {
|
|
||||||
log.Warnln("attribute match no rule: geosite: %s", siteWithAttr)
|
|
||||||
}
|
|
||||||
|
|
||||||
return filteredDomains, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *loader) LoadGeoIP(country string) ([]*router.CIDR, error) {
|
func (l *loader) LoadGeoIP(country string) ([]*router.CIDR, error) {
|
||||||
|
|
|
@ -14,6 +14,5 @@ type LoaderImplementation interface {
|
||||||
type Loader interface {
|
type Loader interface {
|
||||||
LoaderImplementation
|
LoaderImplementation
|
||||||
LoadGeoSite(list string) ([]*router.Domain, error)
|
LoadGeoSite(list string) ([]*router.Domain, error)
|
||||||
LoadGeoSiteWithAttr(file string, siteWithAttr string) ([]*router.Domain, error)
|
|
||||||
LoadGeoIP(country string) ([]*router.CIDR, error)
|
LoadGeoIP(country string) ([]*router.CIDR, error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
package geodata
|
package geodata
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"golang.org/x/sync/singleflight"
|
"golang.org/x/sync/singleflight"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/component/geodata/router"
|
"github.com/Dreamacro/clash/component/geodata/router"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
|
"github.com/Dreamacro/clash/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
var geoLoaderName = "memconservative"
|
var geoLoaderName = "memconservative"
|
||||||
|
@ -51,18 +53,52 @@ func LoadGeoSiteMatcher(countryCode string) (*router.DomainMatcher, int, error)
|
||||||
}
|
}
|
||||||
countryCode = strings.ToLower(countryCode)
|
countryCode = strings.ToLower(countryCode)
|
||||||
|
|
||||||
v, err, _ := loadGeoSiteMatcherSF.Do(countryCode, func() (interface{}, error) {
|
parts := strings.Split(countryCode, "@")
|
||||||
|
if len(parts) == 0 {
|
||||||
|
return nil, 0, errors.New("empty rule")
|
||||||
|
}
|
||||||
|
listName := strings.TrimSpace(parts[0])
|
||||||
|
attrVal := parts[1:]
|
||||||
|
|
||||||
|
if len(listName) == 0 {
|
||||||
|
return nil, 0, fmt.Errorf("empty listname in rule: %s", countryCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
v, err, shared := loadGeoSiteMatcherSF.Do(listName, func() (interface{}, error) {
|
||||||
geoLoader, err := GetGeoDataLoader(geoLoaderName)
|
geoLoader, err := GetGeoDataLoader(geoLoaderName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return geoLoader.LoadGeoSite(countryCode)
|
return geoLoader.LoadGeoSite(listName)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if !shared {
|
||||||
|
loadGeoSiteMatcherSF.Forget(listName) // don't store the error result
|
||||||
|
}
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
domains := v.([]*router.Domain)
|
domains := v.([]*router.Domain)
|
||||||
|
|
||||||
|
attrs := parseAttrs(attrVal)
|
||||||
|
if attrs.IsEmpty() {
|
||||||
|
if strings.Contains(countryCode, "@") {
|
||||||
|
log.Warnln("empty attribute list: %s", countryCode)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
filteredDomains := make([]*router.Domain, 0, len(domains))
|
||||||
|
hasAttrMatched := false
|
||||||
|
for _, domain := range domains {
|
||||||
|
if attrs.Match(domain) {
|
||||||
|
hasAttrMatched = true
|
||||||
|
filteredDomains = append(filteredDomains, domain)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !hasAttrMatched {
|
||||||
|
log.Warnln("attribute match no rule: geosite: %s", countryCode)
|
||||||
|
}
|
||||||
|
domains = filteredDomains
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
linear: linear algorithm
|
linear: linear algorithm
|
||||||
matcher, err := router.NewDomainMatcher(domains)
|
matcher, err := router.NewDomainMatcher(domains)
|
||||||
|
@ -90,7 +126,7 @@ func LoadGeoIPMatcher(country string) (*router.GeoIPMatcher, int, error) {
|
||||||
}
|
}
|
||||||
country = strings.ToLower(country)
|
country = strings.ToLower(country)
|
||||||
|
|
||||||
v, err, _ := loadGeoIPMatcherSF.Do(country, func() (interface{}, error) {
|
v, err, shared := loadGeoIPMatcherSF.Do(country, func() (interface{}, error) {
|
||||||
geoLoader, err := GetGeoDataLoader(geoLoaderName)
|
geoLoader, err := GetGeoDataLoader(geoLoaderName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -98,6 +134,9 @@ func LoadGeoIPMatcher(country string) (*router.GeoIPMatcher, int, error) {
|
||||||
return geoLoader.LoadGeoIP(country)
|
return geoLoader.LoadGeoIP(country)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if !shared {
|
||||||
|
loadGeoIPMatcherSF.Forget(country) // don't store the error result
|
||||||
|
}
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
records := v.([]*router.CIDR)
|
records := v.([]*router.CIDR)
|
||||||
|
|
Loading…
Reference in a new issue