import { BurpaStateLens } from "./burpastate.js"; import { DatagramShort, isResponse } from "../Independents/Datagram/datagram.js" import { GatewayProxy } from "./GatewayProxy.js"; import { TemporaryHost } from "./Host.js"; import { HostName, HostNameTemplate } from "../Independents/DNS/HostName.js"; import { Resolve } from "../Independents/DNS/Resolve.js"; import { CBurpastateWrapper } from "./burpastate"; import { Datagram } from "../Independents/Datagram/datagram-types.js" import { Vagrant } from "./Host.js"; import { timeStamp } from "console"; import { Gateway } from "./Gateway.js"; import { processType } from "../Independents/util/misc.js"; export function RouteGatewayDatagram(state: CBurpastateWrapper, datagram: Datagram, lgw: Gateway, to: string, ton: HostName) { let gwp = lgw.findGatewayProxy(to); if (gwp) { gwp.transmitDatagram(datagram); return; } gwp = lgw.extension.upstreamGateway; if (gwp) { gwp.transmitDatagram(datagram); return; } Send502(state, datagram, "Reject", ton.name); return; } function Send502(state: CBurpastateWrapper, datagram: Datagram, action: string, closest: string) { let host = state.getHost502(action, () => ({ status: 502, final: false, body: { error: "host-not-found", message: `Currently no host ${datagram.to} at ${processType()}. Available local hosts are ${state.debugLocalHosts()}. Available downstream transports are ${state.debugTransports()}. Can't deliver ${DatagramShort(datagram)}.`, closest } })); host.onReceiveDatagram(datagram); } export function RouteDatagram(state: CBurpastateWrapper, datagram: Datagram) { _routeDatagram(state, datagram); } function _routeDatagram(state: CBurpastateWrapper, datagram: Datagram) { let lgw = state.LocalGateway(); let whole = state.whole.persistent; if (datagram.trail.indexOf(lgw.alias.name) !== -1) { datagram.trail.push(lgw.alias.name); console.error(`Detected routing circularity for datagram ${DatagramShort(datagram)}`, datagram) return; } datagram.trail.push(lgw.alias.name); let to = datagram.to; let ton = new HostName(to); let foundLocally = state.findLocalHost(to); if (foundLocally) { // The datagram was addressed to this gateway or a local vagrant. Lets deliver it. //console.log(`Datagram ${DatagramShort(datagram)} reached its destination ${to}`); //console.log(`FOUND LOCAL HOST ${to}`, local.constructor.name); foundLocally.onReceiveDatagram(datagram) return; } if (ton.isGateway()) { //console.log("THIS IS A GATEWAY ", to, ton.first.name) return RouteGatewayDatagram(state, datagram, lgw, to, ton); } const attached = whole.rootHost && whole.rootGateway; let root: undefined | HostName = undefined; if (attached) { let rootgw = new HostName(whole.rootGateway!); root = new HostName(whole.rootHost!); //console.log(`ATTACHED ROUTING ${DatagramShort(datagram)} FROM ${datagram.from} TO ${datagram.to} TO DOWNSTREAM GATEWAY`) // let gwp: GatewayProxy | null = lgw.findGatewayProxy(ton.name); // lgw.downstreamGateways[]; // if (gwp) { // console.log(`ROUTING ${DatagramShort(datagram)} FROM ${datagram.from} TO ${datagram.to} TO DOWNSTREAM GATEWAY`) // gwp.transmitDatagram(datagram); // return; // } let atRootGw = lgw.alias.name == rootgw.name; if (!atRootGw) { let goUpstream = false; if (ton.name == rootgw.name || ton.isDownstreamOf(rootgw)) { goUpstream = true; } else if (ton.name == root.name || ton.isDownstreamOf(root)) { //lgw.spawnThisGatewayAsFarUpstreamAsNeeded(ton); goUpstream = true; } // if (!lgw.extension.upstreamGateway) { // lgw.assureUpstreamTransport(); // } lgw.registerAtUpstream(ton.name); if (goUpstream) { let gwp = lgw.extension.upstreamGateway; gwp.transmitDatagram(datagram); return; } } // The receiver is a distant vagrant or an external http server. Try to find its whereabouts let unresolved = Resolve.fromHostName(ton); for (let v of state.hosts.filter(e => e instanceof Vagrant)) { for (let or of Object.values(v.childHosts)) { let orResolve = or.getResolve() //console.log(`unresolved ${v.alias.name}`, JSON.stringify(orResolve)); unresolved = unresolved.learnFrom(orResolve); } } let closest = unresolved.closestResolvedGateway; if (closest) { console.warn("closest", closest.debugStr) let gwn = closest.gateway!; let gw = lgw.findGatewayProxy(gwn); if (gw) { //console.log("SHOULD ROUTE TO GATEWAY", gwn); gw.transmitDatagram(datagram); return; } } } if (ton.isLocal() || (root && ton.isDownstreamOf(root))) { let daddy = state.findLocalHost(ton.parent); if (daddy) { console.warn(`Cannot route datagram ${DatagramShort(datagram)} as the host ${ton.first.name} has not been spawned at ${ton.parent}.`); daddy.addToInbox("vagrant", datagram); Send502(state, datagram, "Buffer", ton.parent); return; } return; } console.warn(`The receiver ${ton.name} is an external http host`); let httpGw = lgw.getGatewayProxy(`http-${lgw.hostId}`) as GatewayProxy; httpGw.transmitDatagram(datagram); // } // console.warn(`Cannot route ${DatagramShort(datagram)} to ${datagram.to} at ${lgw.publicAlias?.name}`); }