chore: 更新geox时通过内存存储
This commit is contained in:
parent
23cfe20eab
commit
fa6c28e4e4
6 changed files with 103 additions and 86 deletions
|
@ -92,7 +92,7 @@ func (f *Fallback) findAliveProxy(touch bool) C.Proxy {
|
|||
return al
|
||||
}
|
||||
|
||||
func (f *Fallback) Set(name string) (err error) {
|
||||
func (f *Fallback) Set(name string) error {
|
||||
var p C.Proxy
|
||||
for _, proxy := range f.GetProxies(false) {
|
||||
if proxy.Name() == name {
|
||||
|
|
|
@ -30,7 +30,7 @@ func (l *loader) LoadGeoSiteWithAttr(file string, siteWithAttr string) ([]*route
|
|||
return nil, fmt.Errorf("empty listname in rule: %s", siteWithAttr)
|
||||
}
|
||||
|
||||
domains, err := l.LoadSite(file, list)
|
||||
domains, err := l.LoadSiteByPath(file, list)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ func (l *loader) LoadGeoSiteWithAttr(file string, siteWithAttr string) ([]*route
|
|||
}
|
||||
|
||||
func (l *loader) LoadGeoIP(country string) ([]*router.CIDR, error) {
|
||||
return l.LoadIP(C.GeoipName, country)
|
||||
return l.LoadIPByPath(C.GeoipName, country)
|
||||
}
|
||||
|
||||
var loaders map[string]func() LoaderImplementation
|
||||
|
|
|
@ -5,8 +5,10 @@ import (
|
|||
)
|
||||
|
||||
type LoaderImplementation interface {
|
||||
LoadSite(filename, list string) ([]*router.Domain, error)
|
||||
LoadIP(filename, country string) ([]*router.CIDR, error)
|
||||
LoadSiteByPath(filename, list string) ([]*router.Domain, error)
|
||||
LoadSiteByBytes(geositeBytes []byte, list string) ([]*router.Domain, error)
|
||||
LoadIPByPath(filename, country string) ([]*router.CIDR, error)
|
||||
LoadIPByBytes(geoipBytes []byte, country string) ([]*router.CIDR, error)
|
||||
}
|
||||
|
||||
type Loader interface {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package memconservative
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
|
@ -13,7 +14,7 @@ type memConservativeLoader struct {
|
|||
geositecache GeoSiteCache
|
||||
}
|
||||
|
||||
func (m *memConservativeLoader) LoadIP(filename, country string) ([]*router.CIDR, error) {
|
||||
func (m *memConservativeLoader) LoadIPByPath(filename, country string) ([]*router.CIDR, error) {
|
||||
defer runtime.GC()
|
||||
geoip, err := m.geoipcache.Unmarshal(filename, country)
|
||||
if err != nil {
|
||||
|
@ -22,7 +23,11 @@ func (m *memConservativeLoader) LoadIP(filename, country string) ([]*router.CIDR
|
|||
return geoip.Cidr, nil
|
||||
}
|
||||
|
||||
func (m *memConservativeLoader) LoadSite(filename, list string) ([]*router.Domain, error) {
|
||||
func (m *memConservativeLoader) LoadIPByBytes(geoipBytes []byte, country string) ([]*router.CIDR, error) {
|
||||
return nil, errors.New("memConservative do not support LoadIPByBytes")
|
||||
}
|
||||
|
||||
func (m *memConservativeLoader) LoadSiteByPath(filename, list string) ([]*router.Domain, error) {
|
||||
defer runtime.GC()
|
||||
geosite, err := m.geositecache.Unmarshal(filename, list)
|
||||
if err != nil {
|
||||
|
@ -31,6 +36,10 @@ func (m *memConservativeLoader) LoadSite(filename, list string) ([]*router.Domai
|
|||
return geosite.Domain, nil
|
||||
}
|
||||
|
||||
func (m *memConservativeLoader) LoadSiteByBytes(geositeBytes []byte, list string) ([]*router.Domain, error) {
|
||||
return nil, errors.New("memConservative do not support LoadSiteByBytes")
|
||||
}
|
||||
|
||||
func newMemConservativeLoader() geodata.LoaderImplementation {
|
||||
return &memConservativeLoader{make(map[string]*router.GeoIP), make(map[string]*router.GeoSite)}
|
||||
}
|
||||
|
|
|
@ -29,11 +29,7 @@ func ReadAsset(file string) ([]byte, error) {
|
|||
return ReadFile(C.Path.GetAssetLocation(file))
|
||||
}
|
||||
|
||||
func loadIP(filename, country string) ([]*router.CIDR, error) {
|
||||
geoipBytes, err := ReadAsset(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open file: %s, base error: %s", filename, err.Error())
|
||||
}
|
||||
func loadIP(geoipBytes []byte, country string) ([]*router.CIDR, error) {
|
||||
var geoipList router.GeoIPList
|
||||
if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil {
|
||||
return nil, err
|
||||
|
@ -45,14 +41,10 @@ func loadIP(filename, country string) ([]*router.CIDR, error) {
|
|||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("country not found in %s%s%s", filename, ": ", country)
|
||||
return nil, fmt.Errorf("country %s not found", country)
|
||||
}
|
||||
|
||||
func loadSite(filename, list string) ([]*router.Domain, error) {
|
||||
geositeBytes, err := ReadAsset(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open file: %s, base error: %s", filename, err.Error())
|
||||
}
|
||||
func loadSite(geositeBytes []byte, list string) ([]*router.Domain, error) {
|
||||
var geositeList router.GeoSiteList
|
||||
if err := proto.Unmarshal(geositeBytes, &geositeList); err != nil {
|
||||
return nil, err
|
||||
|
@ -64,17 +56,33 @@ func loadSite(filename, list string) ([]*router.Domain, error) {
|
|||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("list not found in %s%s%s", filename, ": ", list)
|
||||
return nil, fmt.Errorf("list %s not found", list)
|
||||
}
|
||||
|
||||
type standardLoader struct{}
|
||||
|
||||
func (d standardLoader) LoadSite(filename, list string) ([]*router.Domain, error) {
|
||||
return loadSite(filename, list)
|
||||
func (d standardLoader) LoadSiteByPath(filename, list string) ([]*router.Domain, error) {
|
||||
geositeBytes, err := ReadAsset(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open file: %s, base error: %s", filename, err.Error())
|
||||
}
|
||||
return loadSite(geositeBytes, list)
|
||||
}
|
||||
|
||||
func (d standardLoader) LoadIP(filename, country string) ([]*router.CIDR, error) {
|
||||
return loadIP(filename, country)
|
||||
func (d standardLoader) LoadSiteByBytes(geositeBytes []byte, list string) ([]*router.Domain, error) {
|
||||
return loadSite(geositeBytes, list)
|
||||
}
|
||||
|
||||
func (d standardLoader) LoadIPByPath(filename, country string) ([]*router.CIDR, error) {
|
||||
geoipBytes, err := ReadAsset(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open file: %s, base error: %s", filename, err.Error())
|
||||
}
|
||||
return loadIP(geoipBytes, country)
|
||||
}
|
||||
|
||||
func (d standardLoader) LoadIPByBytes(geoipBytes []byte, country string) ([]*router.CIDR, error) {
|
||||
return loadIP(geoipBytes, country)
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
|
|
@ -6,77 +6,75 @@ import (
|
|||
_ "github.com/Dreamacro/clash/component/geodata/standard"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/oschwald/geoip2-golang"
|
||||
"os"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func UpdateGeoDatabases() error {
|
||||
var (
|
||||
tmpMMDB = C.Path.Resolve("temp_country.mmdb")
|
||||
tmpGepIP = C.Path.Resolve("temp_geoip.dat")
|
||||
tmpGeoSite = C.Path.Resolve("temp_geosite.dat")
|
||||
)
|
||||
|
||||
if C.GeodataMode {
|
||||
if err := downloadGeoIP(tmpGepIP); err != nil {
|
||||
return fmt.Errorf("can't download GeoIP database file: %w", err)
|
||||
}
|
||||
|
||||
if err := verifyGeoSite("temp_geoip.dat"); err != nil {
|
||||
_ = os.Remove(tmpGepIP)
|
||||
return fmt.Errorf("invalid GeoIP database file: %s", err)
|
||||
}
|
||||
|
||||
if err := os.Rename(tmpGepIP, C.Path.GeoIP()); err != nil {
|
||||
return fmt.Errorf("can't rename MMDB database file: %w", err)
|
||||
}
|
||||
|
||||
} else {
|
||||
if err := downloadMMDB(tmpMMDB); err != nil {
|
||||
return fmt.Errorf("can't download MMDB database file: %w", err)
|
||||
}
|
||||
|
||||
if err := verifyMMDB("temp_country.mmdb"); err != nil {
|
||||
_ = os.Remove(tmpMMDB)
|
||||
return fmt.Errorf("invalid MMDB database file: %s", err)
|
||||
}
|
||||
|
||||
if err := os.Rename(tmpMMDB, C.Path.MMDB()); err != nil {
|
||||
return fmt.Errorf("can't rename MMDB database file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := downloadGeoSite(tmpGeoSite); err != nil {
|
||||
return fmt.Errorf("can't download GeoSite database file: %w", err)
|
||||
}
|
||||
|
||||
if err := verifyGeoSite("temp_geosite.dat"); err != nil {
|
||||
_ = os.Remove(tmpGeoSite)
|
||||
return fmt.Errorf("invalid GeoSite database file: %s", err)
|
||||
}
|
||||
|
||||
if err := os.Rename(tmpGeoSite, C.Path.GeoSite()); err != nil {
|
||||
return fmt.Errorf("can't rename GeoSite database file: %w", err)
|
||||
}
|
||||
runtime.GC()
|
||||
return nil
|
||||
}
|
||||
|
||||
func verifyMMDB(path string) error {
|
||||
instance, err := geoip2.Open(path)
|
||||
if err == nil {
|
||||
_ = instance.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func verifyGeoSite(path string) error {
|
||||
defer runtime.GC()
|
||||
geoLoader, err := geodata.GetGeoDataLoader("standard")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = geoLoader.LoadSite(path, "cn")
|
||||
if C.GeodataMode {
|
||||
data, err := downloadForBytes(C.GeoIpUrl)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't download GeoIP database file: %w", err)
|
||||
}
|
||||
|
||||
return err
|
||||
if _, err = geoLoader.LoadIPByBytes(data, "cn"); err != nil {
|
||||
return fmt.Errorf("invalid GeoIP database file: %s", err)
|
||||
}
|
||||
|
||||
if saveFile(data, C.Path.GeoIP()) != nil {
|
||||
return fmt.Errorf("can't save GeoIP database file: %w", err)
|
||||
}
|
||||
|
||||
} else {
|
||||
data, err := downloadForBytes(C.MmdbUrl)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't download MMDB database file: %w", err)
|
||||
}
|
||||
|
||||
instance, err := geoip2.FromBytes(data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid MMDB database file: %s", err)
|
||||
}
|
||||
_ = instance.Close()
|
||||
|
||||
if saveFile(data, C.Path.MMDB()) != nil {
|
||||
return fmt.Errorf("can't save MMDB database file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
data, err := downloadForBytes(C.GeoSiteUrl)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't download GeoSite database file: %w", err)
|
||||
}
|
||||
|
||||
if _, err = geoLoader.LoadSiteByBytes(data, "cn"); err != nil {
|
||||
return fmt.Errorf("invalid GeoSite database file: %s", err)
|
||||
}
|
||||
|
||||
if saveFile(data, C.Path.GeoSite()) != nil {
|
||||
return fmt.Errorf("can't save GeoSite database file: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func downloadForBytes(url string) ([]byte, error) {
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return ioutil.ReadAll(resp.Body)
|
||||
}
|
||||
|
||||
func saveFile(bytes []byte, path string) error {
|
||||
return ioutil.WriteFile(path, bytes, 0o644)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue