use crate::IpInfo;
use crate::mmdb::mmdb_reader::MmdbReader;
use crate::mmdb::refresh_mmdb_data::refresh_mmdb_data;
use maxminddb::geoip2::{Asn, City};
use nullnet_liberror::{Error, ErrorHandler, Location, location};
use std::sync::{Arc, RwLock};
pub(crate) struct MmdbConfig {
location_reader: Arc<RwLock<MmdbReader>>,
asn_reader: Arc<RwLock<MmdbReader>>,
}
impl MmdbConfig {
pub(crate) fn new(location_url: &str, asn_url: &str, api_key: &str, refresh_days: u64) -> Self {
let location_url = location_url.replace("{api_key}", api_key);
let asn_url = asn_url.replace("{api_key}", api_key);
let location_reader = Arc::new(RwLock::new(MmdbReader::default()));
let location_reader_2 = location_reader.clone();
tokio::spawn(async move {
refresh_mmdb_data(location_reader_2, &location_url, refresh_days).await;
});
let asn_reader = Arc::new(RwLock::new(MmdbReader::default()));
let asn_reader_2 = asn_reader.clone();
tokio::spawn(async move {
refresh_mmdb_data(asn_reader_2, &asn_url, refresh_days).await;
});
Self {
location_reader,
asn_reader,
}
}
pub(crate) fn lookup_ip(&self, ip: &str) -> Result<IpInfo, Error> {
let ip = ip.parse().handle_err(location!())?;
let location_reader = self.location_reader.read().handle_err(location!())?;
let location = location_reader.lookup::<City>(ip);
let asn_reader = self.asn_reader.read().handle_err(location!())?;
let asn = asn_reader.lookup::<Asn>(ip);
Ok(IpInfo::from_mmdb(location.as_ref(), asn.as_ref()))
}
}