123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- package geodb
- import (
- _ "embed"
- "net/http"
- "os"
- "sync"
- "time"
- "imuslab.com/zoraxy/mod/database"
- "imuslab.com/zoraxy/mod/info/logger"
- "imuslab.com/zoraxy/mod/netutils"
- "imuslab.com/zoraxy/mod/utils"
- )
- //go:embed geoipv4.csv
- var geoipv4 []byte //Geodb dataset for ipv4
- //go:embed geoipv6.csv
- var geoipv6 []byte //Geodb dataset for ipv6
- type Store struct {
- geodb [][]string //Parsed geodb list
- geodbIpv6 [][]string //Parsed geodb list for ipv6
- geotrie *trie
- geotrieIpv6 *trie
- sysdb *database.Database
- slowLookupCacheIpv4 sync.Map //Cache for slow lookup, ip -> cc
- slowLookupCacheIpv6 sync.Map //Cache for slow lookup ipv6, ip -> cc
- cacheClearTicker *time.Ticker //Ticker for clearing cache
- cacheClearTickerStopChan chan bool //Stop channel for cache clear ticker
- option *StoreOptions
- }
- type StoreOptions struct {
- AllowSlowIpv4LookUp bool
- AllowSlowIpv6Lookup bool
- Logger *logger.Logger
- SlowLookupCacheClearInterval time.Duration //Clear slow lookup cache interval
- }
- type CountryInfo struct {
- CountryIsoCode string
- ContinetCode string
- }
- func NewGeoDb(sysdb *database.Database, option *StoreOptions) (*Store, error) {
- //Check if external geoDB data is available
- if utils.FileExists("./conf/geodb/geoipv4.csv") {
- externalV4Db, err := os.ReadFile("./conf/geodb/geoipv4.csv")
- if err == nil {
- option.Logger.PrintAndLog("GeoDB", "External GeoDB data found, using external IPv4 GeoIP data", nil)
- geoipv4 = externalV4Db
- }
- }
- if utils.FileExists("./conf/geodb/geoipv6.csv") {
- externalV6Db, err := os.ReadFile("./conf/geodb/geoipv6.csv")
- if err == nil {
- option.Logger.PrintAndLog("GeoDB", "External GeoDB data found, using external IPv6 GeoIP data", nil)
- geoipv6 = externalV6Db
- }
- }
- parsedGeoData, err := parseCSV(geoipv4)
- if err != nil {
- return nil, err
- }
- parsedGeoDataIpv6, err := parseCSV(geoipv6)
- if err != nil {
- return nil, err
- }
- var ipv4Trie *trie
- if !option.AllowSlowIpv4LookUp {
- ipv4Trie = constrctTrieTree(parsedGeoData)
- }
- var ipv6Trie *trie
- if !option.AllowSlowIpv6Lookup {
- ipv6Trie = constrctTrieTree(parsedGeoDataIpv6)
- }
- if option.SlowLookupCacheClearInterval == 0 {
- option.SlowLookupCacheClearInterval = 30 * time.Minute
- }
- //Create a new store
- thisGeoDBStore := &Store{
- geodb: parsedGeoData,
- geotrie: ipv4Trie,
- geodbIpv6: parsedGeoDataIpv6,
- geotrieIpv6: ipv6Trie,
- sysdb: sysdb,
- slowLookupCacheIpv4: sync.Map{},
- slowLookupCacheIpv6: sync.Map{},
- cacheClearTicker: time.NewTicker(option.SlowLookupCacheClearInterval),
- cacheClearTickerStopChan: make(chan bool),
- option: option,
- }
- //Start cache clear ticker
- if option.AllowSlowIpv4LookUp || option.AllowSlowIpv6Lookup {
- go func(store *Store) {
- for {
- select {
- case <-store.cacheClearTickerStopChan:
- return
- case <-thisGeoDBStore.cacheClearTicker.C:
- thisGeoDBStore.slowLookupCacheIpv4 = sync.Map{}
- thisGeoDBStore.slowLookupCacheIpv6 = sync.Map{}
- }
- }
- }(thisGeoDBStore)
- }
- return thisGeoDBStore, nil
- }
- func (s *Store) ResolveCountryCodeFromIP(ipstring string) (*CountryInfo, error) {
- cc := s.search(ipstring)
- return &CountryInfo{
- CountryIsoCode: cc,
- ContinetCode: "",
- }, nil
- }
- // Close the store
- func (s *Store) Close() {
- if s.option.AllowSlowIpv4LookUp || s.option.AllowSlowIpv6Lookup {
- //Stop cache clear ticker
- s.cacheClearTickerStopChan <- true
- }
- }
- func (s *Store) GetRequesterCountryISOCode(r *http.Request) string {
- ipAddr := netutils.GetRequesterIP(r)
- if ipAddr == "" {
- return ""
- }
- if netutils.IsPrivateIP(ipAddr) {
- return "LAN"
- }
- countryCode, err := s.ResolveCountryCodeFromIP(ipAddr)
- if err != nil {
- return ""
- }
- return countryCode.CountryIsoCode
- }
|