fix: geoip mmdb/geodata init

This commit is contained in:
metacubex 2023-01-09 21:07:31 +08:00
parent b4503908df
commit e9a7e104c0
6 changed files with 101 additions and 92 deletions

View file

@ -2,6 +2,7 @@ package geodata
import ( import (
"fmt" "fmt"
"github.com/Dreamacro/clash/component/mmdb"
C "github.com/Dreamacro/clash/constant" C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/log" "github.com/Dreamacro/clash/log"
"io" "io"
@ -9,7 +10,8 @@ import (
"os" "os"
) )
var initFlag bool var initGeoSite bool
var initGeoIP int
func InitGeoSite() error { func InitGeoSite() error {
if _, err := os.Stat(C.Path.GeoSite()); os.IsNotExist(err) { if _, err := os.Stat(C.Path.GeoSite()); os.IsNotExist(err) {
@ -18,8 +20,9 @@ func InitGeoSite() error {
return fmt.Errorf("can't download GeoSite.dat: %s", err.Error()) return fmt.Errorf("can't download GeoSite.dat: %s", err.Error())
} }
log.Infoln("Download GeoSite.dat finish") log.Infoln("Download GeoSite.dat finish")
initGeoSite = false
} }
if !initFlag { if !initGeoSite {
if err := Verify(C.GeositeName); err != nil { if err := Verify(C.GeositeName); err != nil {
log.Warnln("GeoSite.dat invalid, remove and download: %s", err) log.Warnln("GeoSite.dat invalid, remove and download: %s", err)
if err := os.Remove(C.Path.GeoSite()); err != nil { if err := os.Remove(C.Path.GeoSite()); err != nil {
@ -29,7 +32,7 @@ func InitGeoSite() error {
return fmt.Errorf("can't download GeoSite.dat: %s", err.Error()) return fmt.Errorf("can't download GeoSite.dat: %s", err.Error())
} }
} }
initFlag = true initGeoSite = true
} }
return nil return nil
} }
@ -50,3 +53,68 @@ func downloadGeoSite(path string) (err error) {
return err return err
} }
func downloadGeoIP(path string) (err error) {
resp, err := http.Get(C.GeoIpUrl)
if err != nil {
return
}
defer resp.Body.Close()
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0o644)
if err != nil {
return err
}
defer f.Close()
_, err = io.Copy(f, resp.Body)
return err
}
func InitGeoIP() error {
if C.GeodataMode {
if _, err := os.Stat(C.Path.GeoIP()); os.IsNotExist(err) {
log.Infoln("Can't find GeoIP.dat, start download")
if err := downloadGeoIP(C.Path.GeoIP()); err != nil {
return fmt.Errorf("can't download GeoIP.dat: %s", err.Error())
}
log.Infoln("Download GeoIP.dat finish")
initGeoIP = 0
}
if initGeoIP != 1 {
if err := Verify(C.GeoipName); err != nil {
log.Warnln("GeoIP.dat invalid, remove and download: %s", err)
if err := os.Remove(C.Path.GeoIP()); err != nil {
return fmt.Errorf("can't remove invalid GeoIP.dat: %s", err.Error())
}
if err := downloadGeoIP(C.Path.GeoIP()); err != nil {
return fmt.Errorf("can't download GeoIP.dat: %s", err.Error())
}
}
initGeoIP = 1
}
return nil
}
if _, err := os.Stat(C.Path.MMDB()); os.IsNotExist(err) {
log.Infoln("Can't find MMDB, start download")
if err := mmdb.DownloadMMDB(C.Path.MMDB()); err != nil {
return fmt.Errorf("can't download MMDB: %s", err.Error())
}
}
if initGeoIP != 2 {
if !mmdb.Verify() {
log.Warnln("MMDB invalid, remove and download")
if err := os.Remove(C.Path.MMDB()); err != nil {
return fmt.Errorf("can't remove invalid MMDB: %s", err.Error())
}
if err := mmdb.DownloadMMDB(C.Path.MMDB()); err != nil {
return fmt.Errorf("can't download MMDB: %s", err.Error())
}
}
initGeoIP = 2
}
return nil
}

View file

@ -2,6 +2,9 @@ package mmdb
import ( import (
"github.com/oschwald/geoip2-golang" "github.com/oschwald/geoip2-golang"
"io"
"net/http"
"os"
"sync" "sync"
C "github.com/Dreamacro/clash/constant" C "github.com/Dreamacro/clash/constant"
@ -42,3 +45,20 @@ func Instance() *geoip2.Reader {
return mmdb return mmdb
} }
func DownloadMMDB(path string) (err error) {
resp, err := http.Get(C.MmdbUrl)
if err != nil {
return
}
defer resp.Body.Close()
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0o644)
if err != nil {
return err
}
defer f.Close()
_, err = io.Copy(f, resp.Body)
return err
}

View file

@ -3,92 +3,12 @@ package config
import ( import (
"fmt" "fmt"
"github.com/Dreamacro/clash/component/geodata" "github.com/Dreamacro/clash/component/geodata"
"github.com/Dreamacro/clash/component/mmdb"
"io"
"net/http"
"os" "os"
C "github.com/Dreamacro/clash/constant" C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/log" "github.com/Dreamacro/clash/log"
) )
func downloadMMDB(path string) (err error) {
resp, err := http.Get(C.MmdbUrl)
if err != nil {
return
}
defer resp.Body.Close()
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0o644)
if err != nil {
return err
}
defer f.Close()
_, err = io.Copy(f, resp.Body)
return err
}
func downloadGeoIP(path string) (err error) {
resp, err := http.Get(C.GeoIpUrl)
if err != nil {
return
}
defer resp.Body.Close()
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0o644)
if err != nil {
return err
}
defer f.Close()
_, err = io.Copy(f, resp.Body)
return err
}
func initGeoIP() error {
if C.GeodataMode {
if _, err := os.Stat(C.Path.GeoIP()); os.IsNotExist(err) {
log.Infoln("Can't find GeoIP.dat, start download")
if err := downloadGeoIP(C.Path.GeoIP()); err != nil {
return fmt.Errorf("can't download GeoIP.dat: %s", err.Error())
}
log.Infoln("Download GeoIP.dat finish")
}
if err := geodata.Verify(C.GeoipName); err != nil {
log.Warnln("GeoIP.dat invalid, remove and download: %s", err)
if err := os.Remove(C.Path.GeoIP()); err != nil {
return fmt.Errorf("can't remove invalid GeoIP.dat: %s", err.Error())
}
if err := downloadGeoIP(C.Path.GeoIP()); err != nil {
return fmt.Errorf("can't download GeoIP.dat: %s", err.Error())
}
}
return nil
}
if _, err := os.Stat(C.Path.MMDB()); os.IsNotExist(err) {
log.Infoln("Can't find MMDB, start download")
if err := downloadMMDB(C.Path.MMDB()); err != nil {
return fmt.Errorf("can't download MMDB: %s", err.Error())
}
}
if !mmdb.Verify() {
log.Warnln("MMDB invalid, remove and download")
if err := os.Remove(C.Path.MMDB()); err != nil {
return fmt.Errorf("can't remove invalid MMDB: %s", err.Error())
}
if err := downloadMMDB(C.Path.MMDB()); err != nil {
return fmt.Errorf("can't download MMDB: %s", err.Error())
}
}
return nil
}
// Init prepare necessary files // Init prepare necessary files
func Init(dir string) error { func Init(dir string) error {
// initial homedir // initial homedir
@ -122,7 +42,7 @@ func Init(dir string) error {
C.GeoSiteUrl = rawCfg.GeoXUrl.GeoSite C.GeoSiteUrl = rawCfg.GeoXUrl.GeoSite
C.MmdbUrl = rawCfg.GeoXUrl.Mmdb C.MmdbUrl = rawCfg.GeoXUrl.Mmdb
// initial GeoIP // initial GeoIP
if err := initGeoIP(); err != nil { if err := geodata.InitGeoIP(); err != nil {
return fmt.Errorf("can't initial GeoIP: %w", err) return fmt.Errorf("can't initial GeoIP: %w", err)
} }

View file

@ -6,7 +6,6 @@ import (
var ( var (
errPayload = errors.New("payloadRule error") errPayload = errors.New("payloadRule error")
initFlag bool
noResolve = "no-resolve" noResolve = "no-resolve"
) )

View file

@ -71,6 +71,11 @@ func (g *GEOIP) GetRecodeSize() int {
} }
func NewGEOIP(country string, adapter string, noResolveIP bool) (*GEOIP, error) { func NewGEOIP(country string, adapter string, noResolveIP bool) (*GEOIP, error) {
if err := geodata.InitGeoIP(); err != nil {
log.Errorln("can't initial GeoIP: %s", err)
return nil, err
}
if !C.GeodataMode || strings.EqualFold(country, "LAN") { if !C.GeodataMode || strings.EqualFold(country, "LAN") {
geoip := &GEOIP{ geoip := &GEOIP{
Base: &Base{}, Base: &Base{},

View file

@ -50,12 +50,9 @@ func (gs *GEOSITE) GetRecodeSize() int {
} }
func NewGEOSITE(country string, adapter string) (*GEOSITE, error) { func NewGEOSITE(country string, adapter string) (*GEOSITE, error) {
if !initFlag { if err := geodata.InitGeoSite(); err != nil {
if err := geodata.InitGeoSite(); err != nil { log.Errorln("can't initial GeoSite: %s", err)
log.Errorln("can't initial GeoSite: %s", err) return nil, err
return nil, err
}
initFlag = true
} }
matcher, size, err := geodata.LoadGeoSiteMatcher(country) matcher, size, err := geodata.LoadGeoSiteMatcher(country)
@ -76,4 +73,4 @@ func NewGEOSITE(country string, adapter string) (*GEOSITE, error) {
return geoSite, nil return geoSite, nil
} }
//var _ C.Rule = (*GEOSITE)(nil) var _ C.Rule = (*GEOSITE)(nil)