Add exit node selection to the clients

This commit is contained in:
Owen
2026-07-30 11:57:48 -04:00
parent b0e274f5a9
commit 719baa201e
13 changed files with 190 additions and 80 deletions
@@ -0,0 +1,93 @@
import { db, clients } from "@server/db";
import { MessageHandler } from "@server/routers/ws";
import { exitNodes, Olm } from "@server/db";
import logger from "@server/logger";
import { eq } from "drizzle-orm";
import { listExitNodes } from "#dynamic/lib/exitNodes";
import { calculateExitNodeWeight } from "@server/lib/exitNodes";
export const handleOlmExitNodesRequestMessage: MessageHandler = async (
context
) => {
const { message, client: olmClient, sendToClient } = context;
const olm = olmClient as Olm;
logger.info("Handling exit nodes request olm message!");
if (!olm) {
logger.warn("olm not found");
return;
}
// Get the olm's orgId through the client relationship
if (!olm.clientId) {
logger.warn("olm clientId not found");
return;
}
const [client] = await db
.select({ orgId: clients.orgId })
.from(clients)
.where(eq(clients.clientId, olm.clientId))
.limit(1);
if (!client || !client.orgId) {
logger.warn("client not found");
return;
}
const { noCloud, chainId } = message.data;
const exitNodesList = await listExitNodes(
client.orgId,
true,
noCloud || false,
olm.clientId
); // filter for only the online ones
let lastExitNodeId = null;
if (olm.clientId) {
const [lastExitNode] = await db
.select()
.from(clients)
.where(eq(clients.clientId, olm.clientId))
.limit(1);
lastExitNodeId = lastExitNode?.exitNodeId || null;
}
const exitNodesPayload = await Promise.all(
exitNodesList.map(async (node) => {
const weight = await calculateExitNodeWeight(
node.exitNodeId,
node.maxConnections
);
if (weight === null) {
return null;
}
return {
exitNodeId: node.exitNodeId,
exitNodeName: node.name,
endpoint: node.endpoint,
weight,
wasPreviouslyConnected: node.exitNodeId === lastExitNodeId
};
})
);
// filter out null values
const filteredExitNodes = exitNodesPayload.filter((node) => node !== null);
return {
message: {
type: "olm/ping/exitNodes",
data: {
exitNodes: filteredExitNodes,
chainId: chainId
}
},
broadcast: false, // Send to all clients
excludeSender: false // Include sender in broadcast
};
};