feat(remoteingress): add UDP listen port derivation and edge configuration support

This commit is contained in:
2026-03-19 21:30:06 +00:00
parent 65822278d5
commit a65c2ec096
7 changed files with 68 additions and 10 deletions

View File

@@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@serve.zone/dcrouter',
version: '11.7.1',
version: '11.8.0',
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
}

View File

@@ -94,6 +94,38 @@ export class RemoteIngressManager {
return [...ports].sort((a, b) => a - b);
}
/**
* Derive UDP listen ports for an edge from routes with transport 'udp' or 'all'.
* These ports need UDP listeners on the edge (e.g. for QUIC/HTTP3).
*/
public deriveUdpPortsForEdge(edgeId: string, edgeTags?: string[]): number[] {
const ports = new Set<number>();
for (const route of this.routes) {
if (!route.remoteIngress?.enabled) continue;
// Apply edge filter if present
const filter = route.remoteIngress.edgeFilter;
if (filter && filter.length > 0) {
const idMatch = filter.includes(edgeId);
const tagMatch = edgeTags?.some((tag) => filter.includes(tag)) ?? false;
if (!idMatch && !tagMatch) continue;
}
// Only include ports from routes that listen on UDP
const transport = route.match?.transport;
if (transport === 'udp' || transport === 'all') {
if (route.match?.ports) {
for (const p of extractPorts(route.match.ports)) {
ports.add(p);
}
}
}
}
return [...ports].sort((a, b) => a - b);
}
/**
* Get the effective listen ports for an edge.
* Manual ports are always included. Auto-derived ports are added (union) when autoDerivePorts is true.
@@ -106,6 +138,18 @@ export class RemoteIngressManager {
return [...new Set([...manualPorts, ...derivedPorts])].sort((a, b) => a - b);
}
/**
* Get the effective UDP listen ports for an edge.
* Manual UDP ports are always included. Auto-derived UDP ports are added when autoDerivePorts is true.
*/
public getEffectiveListenPortsUdp(edge: IRemoteIngress): number[] {
const manualPorts = edge.listenPortsUdp || [];
const shouldDerive = edge.autoDerivePorts !== false;
if (!shouldDerive) return [...manualPorts].sort((a, b) => a - b);
const derivedPorts = this.deriveUdpPortsForEdge(edge.id, edge.tags);
return [...new Set([...manualPorts, ...derivedPorts])].sort((a, b) => a - b);
}
/**
* Get manual and derived port breakdown for an edge (used in API responses).
* Derived ports exclude any ports already present in the manual list.
@@ -241,15 +285,18 @@ export class RemoteIngressManager {
/**
* Get the list of allowed edges (enabled only) for the Rust hub.
* Includes listenPortsUdp when routes with transport 'udp' or 'all' are present.
*/
public getAllowedEdges(): Array<{ id: string; secret: string; listenPorts: number[] }> {
const result: Array<{ id: string; secret: string; listenPorts: number[] }> = [];
public getAllowedEdges(): Array<{ id: string; secret: string; listenPorts: number[]; listenPortsUdp?: number[] }> {
const result: Array<{ id: string; secret: string; listenPorts: number[]; listenPortsUdp?: number[] }> = [];
for (const edge of this.edges.values()) {
if (edge.enabled) {
const listenPortsUdp = this.getEffectiveListenPortsUdp(edge);
result.push({
id: edge.id,
secret: edge.secret,
listenPorts: this.getEffectiveListenPorts(edge),
...(listenPortsUdp.length > 0 ? { listenPortsUdp } : {}),
});
}
}