Files
MeWeb/src/MeWeb.Core/Knowledge/Providers.cs
T

119 lines
4.3 KiB
C#
Raw Normal View History

using System.Text.Json;
using System.Text.Json.Serialization;
using MeWeb.Core.Net;
namespace MeWeb.Core.Knowledge;
public class ProviderFact
{
public string Value { get; set; }
public decimal? Price { get; set; }
public string Currency { get; set; }
public string Basis { get; set; }
public string Source { get; set; }
public string Date { get; set; }
}
public class ProviderProfile
{
public string Name { get; set; }
public string Country { get; set; }
public List<uint> Asns { get; set; } = [];
public string Sheet { get; set; }
public ProviderFact Ipv4 { get; set; }
public ProviderFact PublicAddress { get; set; }
public ProviderFact Ipv6 { get; set; }
public ProviderFact Port25 { get; set; }
}
[JsonSourceGenerationOptions(JsonSerializerDefaults.Web)]
[JsonSerializable(typeof(ProviderProfile))]
[JsonSerializable(typeof(List<Carrier>))]
[JsonSerializable(typeof(List<ObservedNetwork>))]
public partial class KnowledgeJsonContext : JsonSerializerContext
{
}
public sealed class KnowledgeBase(IPlatform platform)
{
readonly Lazy<AsnTable> asn = new(LoadAsn);
readonly Lazy<List<ProviderProfile>> providers = new(LoadProviders);
readonly Lazy<NetworkTable> networks = new(LoadNetworks);
readonly Lazy<RegistryTable> registry = new(() => LoadRegistry(platform));
readonly Lazy<Dictionary<string, string>> carriers = new(LoadCarriers);
readonly Lazy<List<ObservedNetwork>> observed = new(LoadObserved);
public bool HasAsnTable => typeof(KnowledgeBase).Assembly.GetManifestResourceInfo("ip2asn.bin") is not null;
public AsnTable Asn => asn.Value;
public IReadOnlyList<ProviderProfile> Providers => providers.Value;
public RegistryTable Registry => registry.Value;
public ProviderProfile ProviderFor(uint number) => number == 0 ? null : Providers.FirstOrDefault(p => p.Asns.Contains(number));
public ObservedNetwork ObservedFor(uint number, bool mobile) =>
number == 0 ? null : observed.Value.FirstOrDefault(o => o.Asn == number && o.Line == (mobile ? ObservedNetwork.Mobile : ObservedNetwork.Home));
public NetworkInfo NetworkFor(uint number) => number == 0 ? null : networks.Value?.Find(number);
public string CarrierFor(string mccMnc) => string.IsNullOrEmpty(mccMnc) ? null : carriers.Value.GetValueOrDefault(mccMnc);
public string NameOf(uint number) => NetworkFor(number)?.Organisation ?? Asn?.Find(number)?.Name;
static NetworkTable LoadNetworks()
{
using var stream = typeof(KnowledgeBase).Assembly.GetManifestResourceStream("networks.bin");
return stream is null ? null : NetworkTable.Read(stream);
}
static RegistryTable LoadRegistry(IPlatform platform)
{
var stream = platform.OpenRegistry();
if (stream is null) return null;
try
{
return RegistryTable.Open(stream);
}
catch (Exception ex) when (ex is IOException or InvalidDataException or EndOfStreamException)
{
stream.Dispose();
return null;
}
}
static Dictionary<string, string> LoadCarriers()
{
using var stream = typeof(KnowledgeBase).Assembly.GetManifestResourceStream("carriers.json");
if (stream is null) return [];
var list = JsonSerializer.Deserialize(stream, KnowledgeJsonContext.Default.ListCarrier) ?? [];
return list.Where(c => c.MccMnc is not null && c.Name is not null).GroupBy(c => c.MccMnc).ToDictionary(g => g.Key, g => g.First().Name);
}
static List<ObservedNetwork> LoadObserved()
{
using var stream = typeof(KnowledgeBase).Assembly.GetManifestResourceStream("observed.json");
return stream is null ? [] : JsonSerializer.Deserialize(stream, KnowledgeJsonContext.Default.ListObservedNetwork) ?? [];
}
static AsnTable LoadAsn()
{
using var stream = typeof(KnowledgeBase).Assembly.GetManifestResourceStream("ip2asn.bin");
return stream is null ? null : AsnTable.Read(stream);
}
static List<ProviderProfile> LoadProviders()
{
var assembly = typeof(KnowledgeBase).Assembly;
var list = new List<ProviderProfile>();
foreach (var name in assembly.GetManifestResourceNames().Where(n => n.StartsWith("isp.", StringComparison.Ordinal)).Order(StringComparer.Ordinal))
{
using var stream = assembly.GetManifestResourceStream(name);
var profile = JsonSerializer.Deserialize(stream, KnowledgeJsonContext.Default.ProviderProfile);
if (profile is not null) list.Add(profile);
}
return list;
}
}