// InitGeoIP opens a GeoIP2/GeoLite2 MaxMind database and prepares
// it for lookups.
func InitGeoIP(config *Config) error {

	discoveryValueHMACKey = config.DiscoveryValueHMACKey

	if config.GeoIPDatabaseFilename != "" {
		var err error
		geoIPReader, err = maxminddb.Open(config.GeoIPDatabaseFilename)
		if err != nil {
			return psiphon.ContextError(err)
		}
		log.WithContext().Info("GeoIP initialized")
	}

	return nil
}
// NewGeoIPService initializes a new GeoIPService.
func NewGeoIPService(
	databaseFilenames []string,
	discoveryValueHMACKey string) (*GeoIPService, error) {

	geoIP := &GeoIPService{
		databases:             make([]*geoIPDatabase, len(databaseFilenames)),
		sessionCache:          cache.New(GEOIP_SESSION_CACHE_TTL, 1*time.Minute),
		discoveryValueHMACKey: discoveryValueHMACKey,
	}

	for i, filename := range databaseFilenames {

		database := &geoIPDatabase{}
		database.ReloadableFile = common.NewReloadableFile(
			filename,
			func(filename string) error {
				maxMindReader, err := maxminddb.Open(filename)
				if err != nil {
					// On error, database state remains the same
					return common.ContextError(err)
				}
				if database.maxMindReader != nil {
					database.maxMindReader.Close()
				}
				database.maxMindReader = maxMindReader
				return nil
			})

		_, err := database.Reload()
		if err != nil {
			return nil, common.ContextError(err)
		}

		geoIP.databases[i] = database
	}

	return geoIP, nil
}