Compare commits
4 Commits
0313921fc8
...
d61fccde7a
Author | SHA1 | Date |
---|---|---|
A1lo | d61fccde7a | |
dependabot[bot] | 0735053348 | |
dependabot[bot] | e41a61c6f7 | |
Allo | 6b25c7e500 |
8
go.mod
8
go.mod
|
@ -22,13 +22,13 @@ require (
|
|||
github.com/vishvananda/netlink v1.2.1-beta.2.0.20230316163032-ced5aaba43e3
|
||||
github.com/xtls/reality v0.0.0-20231112171332-de1173cf2b19
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
||||
golang.org/x/crypto v0.22.0
|
||||
golang.org/x/net v0.24.0
|
||||
golang.org/x/crypto v0.23.0
|
||||
golang.org/x/net v0.25.0
|
||||
golang.org/x/sync v0.7.0
|
||||
golang.org/x/sys v0.20.0
|
||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
||||
google.golang.org/grpc v1.63.2
|
||||
google.golang.org/protobuf v1.34.0
|
||||
google.golang.org/protobuf v1.34.1
|
||||
gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489
|
||||
h12.io/socks v1.0.3
|
||||
lukechampine.com/blake3 v1.3.0
|
||||
|
@ -51,7 +51,7 @@ require (
|
|||
go.uber.org/mock v0.4.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
|
||||
golang.org/x/mod v0.16.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/text v0.15.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.19.0 // indirect
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||
|
|
16
go.sum
16
go.sum
|
@ -181,8 +181,8 @@ golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnf
|
|||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
|
||||
|
@ -203,8 +203,8 @@ golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
|
@ -237,8 +237,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
|
@ -279,8 +279,8 @@ google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3
|
|||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
|
||||
google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
|
||||
google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4=
|
||||
google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
|
||||
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
|
|
@ -73,8 +73,11 @@ func (c *NameServerConfig) Build() (*dns.NameServer, error) {
|
|||
var domains []*dns.NameServer_PriorityDomain
|
||||
var originalRules []*dns.NameServer_OriginalRule
|
||||
|
||||
cache := NewGeoCache()
|
||||
defer cache.Clear()
|
||||
|
||||
for _, rule := range c.Domains {
|
||||
parsedDomain, err := parseDomainRule(rule)
|
||||
parsedDomain, err := cache.ParseDomainRule(rule)
|
||||
if err != nil {
|
||||
return nil, newError("invalid domain rule: ", rule).Base(err)
|
||||
}
|
||||
|
@ -91,7 +94,7 @@ func (c *NameServerConfig) Build() (*dns.NameServer, error) {
|
|||
})
|
||||
}
|
||||
|
||||
geoipList, err := ToCidrList(c.ExpectIPs)
|
||||
geoipList, err := cache.ToCidrList(c.ExpectIPs)
|
||||
if err != nil {
|
||||
return nil, newError("invalid IP rule: ", c.ExpectIPs).Base(err)
|
||||
}
|
||||
|
@ -209,6 +212,9 @@ func (m *HostsWrapper) Build() ([]*dns.Config_HostMapping, error) {
|
|||
}
|
||||
sort.Strings(domains)
|
||||
|
||||
cache := newSiteCache()
|
||||
defer cache.reset()
|
||||
|
||||
for _, domain := range domains {
|
||||
switch {
|
||||
case strings.HasPrefix(domain, "domain:"):
|
||||
|
@ -226,7 +232,7 @@ func (m *HostsWrapper) Build() ([]*dns.Config_HostMapping, error) {
|
|||
if len(listName) == 0 {
|
||||
return nil, newError("empty geosite rule: ", domain)
|
||||
}
|
||||
geositeList, err := loadGeositeWithAttr("geosite.dat", listName)
|
||||
geositeList, err := cache.loadGeositeWithAttr("geosite.dat", listName)
|
||||
if err != nil {
|
||||
return nil, newError("failed to load geosite: ", listName).Base(err)
|
||||
}
|
||||
|
@ -287,7 +293,7 @@ func (m *HostsWrapper) Build() ([]*dns.Config_HostMapping, error) {
|
|||
}
|
||||
filename := kv[0]
|
||||
list := kv[1]
|
||||
geositeList, err := loadGeositeWithAttr(filename, list)
|
||||
geositeList, err := cache.loadGeositeWithAttr(filename, list)
|
||||
if err != nil {
|
||||
return nil, newError("failed to load domain list: ", list, " from ", filename).Base(err)
|
||||
}
|
||||
|
|
|
@ -116,8 +116,11 @@ func (c *RouterConfig) Build() (*router.Config, error) {
|
|||
}
|
||||
}
|
||||
|
||||
cache := NewGeoCache()
|
||||
defer cache.Clear()
|
||||
|
||||
for _, rawRule := range rawRuleList {
|
||||
rule, err := ParseRule(rawRule)
|
||||
rule, err := cache.ParseRule(rawRule)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -195,39 +198,80 @@ func ParseIP(s string) (*router.CIDR, error) {
|
|||
}
|
||||
}
|
||||
|
||||
func loadGeoIP(code string) ([]*router.CIDR, error) {
|
||||
return loadIP("geoip.dat", code)
|
||||
}
|
||||
|
||||
var (
|
||||
FileCache = make(map[string][]byte)
|
||||
IPCache = make(map[string]*router.GeoIP)
|
||||
SiteCache = make(map[string]*router.GeoSite)
|
||||
)
|
||||
|
||||
func loadFile(file string) ([]byte, error) {
|
||||
if FileCache[file] == nil {
|
||||
bs, err := filesystem.ReadAsset(file)
|
||||
if err != nil {
|
||||
return nil, newError("failed to open file: ", file).Base(err)
|
||||
}
|
||||
if len(bs) == 0 {
|
||||
return nil, newError("empty file: ", file)
|
||||
}
|
||||
// Do not cache file, may save RAM when there
|
||||
// are many files, but consume CPU each time.
|
||||
return bs, nil
|
||||
FileCache[file] = bs
|
||||
bs, err := filesystem.ReadAsset(file)
|
||||
if err != nil {
|
||||
return nil, newError("failed to open file: ", file).Base(err)
|
||||
}
|
||||
return FileCache[file], nil
|
||||
if len(bs) == 0 {
|
||||
return nil, newError("empty file: ", file)
|
||||
}
|
||||
return bs, nil
|
||||
}
|
||||
|
||||
func loadIP(file, code string) ([]*router.CIDR, error) {
|
||||
type ipCache struct {
|
||||
fileContent map[string][]byte
|
||||
geoIPs map[string]*router.GeoIP
|
||||
}
|
||||
|
||||
type siteCache struct {
|
||||
fileContent map[string][]byte
|
||||
geoSites map[string]*router.GeoSite
|
||||
}
|
||||
|
||||
// GeoCache is a cache for GeoIP and GeoSite.
|
||||
type GeoCache struct {
|
||||
ipCache *ipCache
|
||||
siteCache *siteCache
|
||||
}
|
||||
|
||||
// NewGeoCache creates a new GeoCache.
|
||||
func NewGeoCache() *GeoCache {
|
||||
return &GeoCache{
|
||||
ipCache: newIPCache(),
|
||||
siteCache: newSiteCache(),
|
||||
}
|
||||
}
|
||||
|
||||
// Clear clears the cache.
|
||||
func (c *GeoCache) Clear() {
|
||||
if c.ipCache.reset() || c.siteCache.reset() {
|
||||
// only trigger GC if there is something to release
|
||||
runtime.GC()
|
||||
}
|
||||
}
|
||||
|
||||
// newIPCache creates a new ipCache.
|
||||
// after use, call close() to release memory.
|
||||
func newIPCache() *ipCache {
|
||||
return &ipCache{
|
||||
fileContent: make(map[string][]byte),
|
||||
geoIPs: make(map[string]*router.GeoIP),
|
||||
}
|
||||
}
|
||||
|
||||
// reset remove the content of ipCache.
|
||||
// returns true if the cache is not empty.
|
||||
func (c *ipCache) reset() bool {
|
||||
if len(c.fileContent) == 0 && len(c.geoIPs) == 0 {
|
||||
return false
|
||||
}
|
||||
c.fileContent = make(map[string][]byte)
|
||||
c.geoIPs = make(map[string]*router.GeoIP)
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *ipCache) loadIP(file, code string) ([]*router.CIDR, error) {
|
||||
index := file + ":" + code
|
||||
if IPCache[index] == nil {
|
||||
bs, err := loadFile(file)
|
||||
if err != nil {
|
||||
return nil, newError("failed to load file: ", file).Base(err)
|
||||
if c.geoIPs[index] == nil {
|
||||
bs := c.fileContent[file]
|
||||
if bs == nil {
|
||||
var err error
|
||||
bs, err = loadFile(file)
|
||||
if err != nil {
|
||||
return nil, newError("failed to load file: ", file).Base(err)
|
||||
}
|
||||
c.fileContent[file] = bs
|
||||
}
|
||||
bs = find(bs, []byte(code))
|
||||
if bs == nil {
|
||||
|
@ -237,19 +281,43 @@ func loadIP(file, code string) ([]*router.CIDR, error) {
|
|||
if err := proto.Unmarshal(bs, &geoip); err != nil {
|
||||
return nil, newError("error unmarshal IP in ", file, ": ", code).Base(err)
|
||||
}
|
||||
defer runtime.GC() // or debug.FreeOSMemory()
|
||||
return geoip.Cidr, nil // do not cache geoip
|
||||
IPCache[index] = &geoip
|
||||
c.geoIPs[index] = &geoip
|
||||
return geoip.Cidr, nil
|
||||
}
|
||||
return IPCache[index].Cidr, nil
|
||||
return c.geoIPs[index].Cidr, nil
|
||||
}
|
||||
|
||||
func loadSite(file, code string) ([]*router.Domain, error) {
|
||||
// newSiteCache creates a new siteCache.
|
||||
// after use, call close() to release memory.
|
||||
func newSiteCache() *siteCache {
|
||||
return &siteCache{
|
||||
fileContent: make(map[string][]byte),
|
||||
geoSites: make(map[string]*router.GeoSite),
|
||||
}
|
||||
}
|
||||
|
||||
// reset remove the content of siteCache.
|
||||
// returns true if the cache is not empty.
|
||||
func (c *siteCache) reset() bool {
|
||||
if len(c.fileContent) == 0 && len(c.geoSites) == 0 {
|
||||
return false
|
||||
}
|
||||
c.fileContent = make(map[string][]byte)
|
||||
c.geoSites = make(map[string]*router.GeoSite)
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *siteCache) loadSite(file, code string) ([]*router.Domain, error) {
|
||||
index := file + ":" + code
|
||||
if SiteCache[index] == nil {
|
||||
bs, err := loadFile(file)
|
||||
if err != nil {
|
||||
return nil, newError("failed to load file: ", file).Base(err)
|
||||
if c.geoSites[index] == nil {
|
||||
bs := c.fileContent[file]
|
||||
if bs == nil {
|
||||
var err error
|
||||
bs, err = loadFile(file)
|
||||
if err != nil {
|
||||
return nil, newError("failed to load file: ", file).Base(err)
|
||||
}
|
||||
c.fileContent[file] = bs
|
||||
}
|
||||
bs = find(bs, []byte(code))
|
||||
if bs == nil {
|
||||
|
@ -259,11 +327,10 @@ func loadSite(file, code string) ([]*router.Domain, error) {
|
|||
if err := proto.Unmarshal(bs, &geosite); err != nil {
|
||||
return nil, newError("error unmarshal Site in ", file, ": ", code).Base(err)
|
||||
}
|
||||
defer runtime.GC() // or debug.FreeOSMemory()
|
||||
return geosite.Domain, nil // do not cache geosite
|
||||
SiteCache[index] = &geosite
|
||||
c.geoSites[index] = &geosite
|
||||
return geosite.Domain, nil
|
||||
}
|
||||
return SiteCache[index].Domain, nil
|
||||
return c.geoSites[index].Domain, nil
|
||||
}
|
||||
|
||||
func DecodeVarint(buf []byte) (x uint64, n int) {
|
||||
|
@ -358,14 +425,14 @@ func parseAttrs(attrs []string) *AttributeList {
|
|||
return al
|
||||
}
|
||||
|
||||
func loadGeositeWithAttr(file string, siteWithAttr string) ([]*router.Domain, error) {
|
||||
func (c *siteCache) loadGeositeWithAttr(file string, siteWithAttr string) ([]*router.Domain, error) {
|
||||
parts := strings.Split(siteWithAttr, "@")
|
||||
if len(parts) == 0 {
|
||||
return nil, newError("empty site")
|
||||
}
|
||||
country := strings.ToUpper(parts[0])
|
||||
attrs := parseAttrs(parts[1:])
|
||||
domains, err := loadSite(file, country)
|
||||
domains, err := c.loadSite(file, country)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -384,10 +451,10 @@ func loadGeositeWithAttr(file string, siteWithAttr string) ([]*router.Domain, er
|
|||
return filteredDomains, nil
|
||||
}
|
||||
|
||||
func parseDomainRule(domain string) ([]*router.Domain, error) {
|
||||
func (c *GeoCache) ParseDomainRule(domain string) ([]*router.Domain, error) {
|
||||
if strings.HasPrefix(domain, "geosite:") {
|
||||
country := strings.ToUpper(domain[8:])
|
||||
domains, err := loadGeositeWithAttr("geosite.dat", country)
|
||||
domains, err := c.siteCache.loadGeositeWithAttr("geosite.dat", country)
|
||||
if err != nil {
|
||||
return nil, newError("failed to load geosite: ", country).Base(err)
|
||||
}
|
||||
|
@ -411,7 +478,7 @@ func parseDomainRule(domain string) ([]*router.Domain, error) {
|
|||
}
|
||||
filename := kv[0]
|
||||
country := kv[1]
|
||||
domains, err := loadGeositeWithAttr(filename, country)
|
||||
domains, err := c.siteCache.loadGeositeWithAttr(filename, country)
|
||||
if err != nil {
|
||||
return nil, newError("failed to load external sites: ", country, " from ", filename).Base(err)
|
||||
}
|
||||
|
@ -454,7 +521,7 @@ func parseDomainRule(domain string) ([]*router.Domain, error) {
|
|||
return []*router.Domain{domainRule}, nil
|
||||
}
|
||||
|
||||
func ToCidrList(ips StringList) ([]*router.GeoIP, error) {
|
||||
func (c *GeoCache) ToCidrList(ips StringList) ([]*router.GeoIP, error) {
|
||||
var geoipList []*router.GeoIP
|
||||
var customCidrs []*router.CIDR
|
||||
|
||||
|
@ -469,7 +536,7 @@ func ToCidrList(ips StringList) ([]*router.GeoIP, error) {
|
|||
if len(country) == 0 {
|
||||
return nil, newError("empty country name in rule")
|
||||
}
|
||||
geoip, err := loadGeoIP(strings.ToUpper(country))
|
||||
geoip, err := c.ipCache.loadIP("geoip.dat", strings.ToUpper(country))
|
||||
if err != nil {
|
||||
return nil, newError("failed to load GeoIP: ", country).Base(err)
|
||||
}
|
||||
|
@ -509,7 +576,7 @@ func ToCidrList(ips StringList) ([]*router.GeoIP, error) {
|
|||
country = country[1:]
|
||||
isReverseMatch = true
|
||||
}
|
||||
geoip, err := loadIP(filename, strings.ToUpper(country))
|
||||
geoip, err := c.ipCache.loadIP(filename, strings.ToUpper(country))
|
||||
if err != nil {
|
||||
return nil, newError("failed to load IPs: ", country, " from ", filename).Base(err)
|
||||
}
|
||||
|
@ -539,7 +606,7 @@ func ToCidrList(ips StringList) ([]*router.GeoIP, error) {
|
|||
return geoipList, nil
|
||||
}
|
||||
|
||||
func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
|
||||
func (c *GeoCache) parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
|
||||
type RawFieldRule struct {
|
||||
RouterRule
|
||||
Domain *StringList `json:"domain"`
|
||||
|
@ -581,7 +648,7 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
|
|||
|
||||
if rawFieldRule.Domain != nil {
|
||||
for _, domain := range *rawFieldRule.Domain {
|
||||
rules, err := parseDomainRule(domain)
|
||||
rules, err := c.ParseDomainRule(domain)
|
||||
if err != nil {
|
||||
return nil, newError("failed to parse domain rule: ", domain).Base(err)
|
||||
}
|
||||
|
@ -591,7 +658,7 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
|
|||
|
||||
if rawFieldRule.Domains != nil {
|
||||
for _, domain := range *rawFieldRule.Domains {
|
||||
rules, err := parseDomainRule(domain)
|
||||
rules, err := c.ParseDomainRule(domain)
|
||||
if err != nil {
|
||||
return nil, newError("failed to parse domain rule: ", domain).Base(err)
|
||||
}
|
||||
|
@ -600,7 +667,7 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
|
|||
}
|
||||
|
||||
if rawFieldRule.IP != nil {
|
||||
geoipList, err := ToCidrList(*rawFieldRule.IP)
|
||||
geoipList, err := c.ToCidrList(*rawFieldRule.IP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -616,7 +683,7 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
|
|||
}
|
||||
|
||||
if rawFieldRule.SourceIP != nil {
|
||||
geoipList, err := ToCidrList(*rawFieldRule.SourceIP)
|
||||
geoipList, err := c.ToCidrList(*rawFieldRule.SourceIP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -652,14 +719,14 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
|
|||
return rule, nil
|
||||
}
|
||||
|
||||
func ParseRule(msg json.RawMessage) (*router.RoutingRule, error) {
|
||||
func (c *GeoCache) ParseRule(msg json.RawMessage) (*router.RoutingRule, error) {
|
||||
rawRule := new(RouterRule)
|
||||
err := json.Unmarshal(msg, rawRule)
|
||||
if err != nil {
|
||||
return nil, newError("invalid router rule").Base(err)
|
||||
}
|
||||
if rawRule.Type == "" || strings.EqualFold(rawRule.Type, "field") {
|
||||
fieldrule, err := parseFieldRule(msg)
|
||||
fieldrule, err := c.parseFieldRule(msg)
|
||||
if err != nil {
|
||||
return nil, newError("invalid field rule").Base(err)
|
||||
}
|
||||
|
|
|
@ -44,7 +44,10 @@ func TestToCidrList(t *testing.T) {
|
|||
"ext-ip:geoiptestrouter.dat:!ca",
|
||||
})
|
||||
|
||||
_, err := ToCidrList(ips)
|
||||
cache := NewGeoCache()
|
||||
defer cache.Clear()
|
||||
|
||||
_, err := cache.ToCidrList(ips)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to parse geoip list, got %s", err)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue