123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- package mmdb
- import (
- "context"
- "io"
- "net/http"
- "os"
- "sync"
- "time"
- mihomoOnce "github.com/metacubex/mihomo/common/once"
- mihomoHttp "github.com/metacubex/mihomo/component/http"
- C "github.com/metacubex/mihomo/constant"
- "github.com/metacubex/mihomo/log"
- "github.com/oschwald/maxminddb-golang"
- )
- type databaseType = uint8
- const (
- typeMaxmind databaseType = iota
- typeSing
- typeMetaV0
- )
- var (
- IPreader IPReader
- ASNreader ASNReader
- IPonce sync.Once
- ASNonce sync.Once
- )
- func LoadFromBytes(buffer []byte) {
- IPonce.Do(func() {
- mmdb, err := maxminddb.FromBytes(buffer)
- if err != nil {
- log.Fatalln("Can't load mmdb: %s", err.Error())
- }
- IPreader = IPReader{Reader: mmdb}
- switch mmdb.Metadata.DatabaseType {
- case "sing-geoip":
- IPreader.databaseType = typeSing
- case "Meta-geoip0":
- IPreader.databaseType = typeMetaV0
- default:
- IPreader.databaseType = typeMaxmind
- }
- })
- }
- func Verify(path string) bool {
- instance, err := maxminddb.Open(path)
- if err == nil {
- instance.Close()
- }
- return err == nil
- }
- func IPInstance() IPReader {
- IPonce.Do(func() {
- mmdbPath := C.Path.MMDB()
- log.Infoln("Load MMDB file: %s", mmdbPath)
- mmdb, err := maxminddb.Open(mmdbPath)
- if err != nil {
- log.Fatalln("Can't load MMDB: %s", err.Error())
- }
- IPreader = IPReader{Reader: mmdb}
- switch mmdb.Metadata.DatabaseType {
- case "sing-geoip":
- IPreader.databaseType = typeSing
- case "Meta-geoip0":
- IPreader.databaseType = typeMetaV0
- default:
- IPreader.databaseType = typeMaxmind
- }
- })
- return IPreader
- }
- func DownloadMMDB(path string) (err error) {
- ctx, cancel := context.WithTimeout(context.Background(), time.Second*90)
- defer cancel()
- resp, err := mihomoHttp.HttpRequest(ctx, C.MmdbUrl, http.MethodGet, http.Header{"User-Agent": {C.UA}}, nil)
- 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 ASNInstance() ASNReader {
- ASNonce.Do(func() {
- ASNPath := C.Path.ASN()
- log.Infoln("Load ASN file: %s", ASNPath)
- asn, err := maxminddb.Open(ASNPath)
- if err != nil {
- log.Fatalln("Can't load ASN: %s", err.Error())
- }
- ASNreader = ASNReader{Reader: asn}
- })
- return ASNreader
- }
- func DownloadASN(path string) (err error) {
- ctx, cancel := context.WithTimeout(context.Background(), time.Second*90)
- defer cancel()
- resp, err := mihomoHttp.HttpRequest(ctx, C.ASNUrl, http.MethodGet, http.Header{"User-Agent": {C.UA}}, nil)
- 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 ReloadIP() {
- mihomoOnce.Reset(&IPonce)
- }
- func ReloadASN() {
- mihomoOnce.Reset(&ASNonce)
- }
|