The 662-line handler (the largest in the file) split into one function per data-source/merge stage: facility+IX-location coordinate resolution (facilities.js), neighbour name-resolution + threat-intel enrichment (enrich-neighbours.js), RIR/country derivation cascade (rir-country.js), visibility/prefix-size computation (routing-info.js), multi-source cross-checks + data-quality scoring (cross-check.js), and a slim orchestrator (index.js) running Phase 0/1 fetch and final result assembly. Verified via node --check, eslint no-undef (2 known bugs remain: compare, webhooks), and smoke-test harness (28/28 match, including a byte-for-byte match on /api/lookup's own large response body -- the strongest possible confirmation this, the most complex handler in the file, was decomposed without changing behavior). server.js: 2917 -> 1734 lines (6838 originally -- 75% reduction so far).
72 lines
3.5 KiB
JavaScript
72 lines
3.5 KiB
JavaScript
const { fetchBgproutesVisibility } = require("../../services/http-helpers");
|
|
|
|
// Compute routing visibility and prefix size distribution.
|
|
async function computeRoutingInfo(prefixes, visibilityData, prefixSizeData) {
|
|
const ipv4Prefixes = prefixes.filter(function(p) { return !p.prefix.includes(":"); });
|
|
const ipv6Prefixes = prefixes.filter(function(p) { return p.prefix.includes(":"); });
|
|
var ipv4VisAvg = 0, ipv6VisAvg = 0, totalRisPeersV4 = 0, totalRisPeersV6 = 0;
|
|
|
|
// Visibility API returns per-RIS-collector data
|
|
// Each collector has ipv4_full_table_peer_count and ipv4_full_table_peers_not_seeing[]
|
|
// Bug 3 fix: visibility API may timeout for large ASNs — handle gracefully
|
|
var visibilities = (visibilityData && visibilityData.data && visibilityData.data.visibilities) || [];
|
|
var v4Seeing = 0, v4Total = 0, v6Seeing = 0, v6Total = 0;
|
|
var visTimedOut = !visibilityData || !visibilityData.data;
|
|
visibilities.forEach(function(v) {
|
|
if (!v || !v.probe) return;
|
|
var v4PeerCount = v.ipv4_full_table_peer_count || 0;
|
|
var v4NotSeeing = (v.ipv4_full_table_peers_not_seeing || []).length;
|
|
var v6PeerCount = v.ipv6_full_table_peer_count || 0;
|
|
var v6NotSeeing = (v.ipv6_full_table_peers_not_seeing || []).length;
|
|
v4Total += v4PeerCount;
|
|
v4Seeing += (v4PeerCount - v4NotSeeing);
|
|
v6Total += v6PeerCount;
|
|
v6Seeing += (v6PeerCount - v6NotSeeing);
|
|
});
|
|
if (v4Total > 0) ipv4VisAvg = Math.round((v4Seeing / v4Total) * 1000) / 10;
|
|
if (v6Total > 0) ipv6VisAvg = Math.round((v6Seeing / v6Total) * 1000) / 10;
|
|
// If visibility API timed out but we have prefixes, try bgproutes.io fallback
|
|
if (visTimedOut && prefixes.length > 0) {
|
|
var fallbackPrefix = prefixes.find(function(p) { return !p.prefix.includes(":"); });
|
|
if (!fallbackPrefix) fallbackPrefix = prefixes[0];
|
|
if (fallbackPrefix) {
|
|
var bgprFallback = await fetchBgproutesVisibility(fallbackPrefix.prefix);
|
|
if (bgprFallback && bgprFallback.vps_seeing > 0) {
|
|
// Estimate visibility: % of VPs seeing the prefix (assume ~300 total RIS-equivalent VPs)
|
|
var estimatedTotal = Math.max(bgprFallback.vps_seeing, 300);
|
|
ipv4VisAvg = Math.round((bgprFallback.vps_seeing / estimatedTotal) * 1000) / 10;
|
|
ipv6VisAvg = -1; // bgproutes fallback is per-prefix, not per-AF aggregate
|
|
totalRisPeersV4 = bgprFallback.vps_seeing;
|
|
console.log("[Visibility] RIPE Stat timed out, used bgproutes.io fallback for " + fallbackPrefix.prefix + ": " + bgprFallback.vps_seeing + " VPs seeing it");
|
|
} else {
|
|
ipv4VisAvg = -1;
|
|
ipv6VisAvg = -1;
|
|
console.log("[Visibility] RIPE Stat timed out and bgproutes.io fallback returned no data");
|
|
}
|
|
} else {
|
|
ipv4VisAvg = -1;
|
|
ipv6VisAvg = -1;
|
|
}
|
|
}
|
|
totalRisPeersV4 = v4Total;
|
|
totalRisPeersV6 = v6Total;
|
|
|
|
// Prefix size distribution: data.ipv4[] and data.ipv6[] arrays with {size, count}
|
|
var psdData = (prefixSizeData && prefixSizeData.data) || {};
|
|
var psV4 = (psdData.ipv4 || []).map(function(e) { return { size: e.size, count: e.count }; }).sort(function(a,b){ return a.size - b.size; });
|
|
var psV6 = (psdData.ipv6 || []).map(function(e) { return { size: e.size, count: e.count }; }).sort(function(a,b){ return a.size - b.size; });
|
|
|
|
return {
|
|
ipv4_prefixes: ipv4Prefixes.length,
|
|
ipv6_prefixes: ipv6Prefixes.length,
|
|
ipv4_visibility_avg: ipv4VisAvg,
|
|
ipv6_visibility_avg: ipv6VisAvg,
|
|
total_ris_peers_v4: totalRisPeersV4,
|
|
total_ris_peers_v6: totalRisPeersV6,
|
|
prefix_sizes_v4: psV4,
|
|
prefix_sizes_v6: psV6,
|
|
};
|
|
}
|
|
|
|
module.exports = { computeRoutingInfo };
|