diff --git a/server/routers/olm/handleOlmLocalMessage.ts b/server/routers/olm/handleOlmLocalMessage.ts new file mode 100644 index 000000000..83ef8cbf1 --- /dev/null +++ b/server/routers/olm/handleOlmLocalMessage.ts @@ -0,0 +1,74 @@ +import { db, sites } from "@server/db"; +import { MessageHandler } from "@server/routers/ws"; +import { clients, Olm } from "@server/db"; +import { and, eq } from "drizzle-orm"; +import { updatePeer as newtUpdatePeer } from "../newt/peers"; +import logger from "@server/logger"; + +export const handleOlmLocalMessage: MessageHandler = async (context) => { + const { message, client: c, sendToClient } = context; + const olm = c as Olm; + + logger.info("Handling local olm message!"); + + if (!olm) { + logger.warn("Olm not found"); + return; + } + + if (!olm.clientId) { + logger.warn("Olm has no client!"); + return; + } + + const clientId = olm.clientId; + + const [client] = await db + .select() + .from(clients) + .where(eq(clients.clientId, clientId)) + .limit(1); + + if (!client) { + logger.warn("Client not found"); + return; + } + + // make sure we hand endpoints for both the site and the client and the lastHolePunch is not too old + if (!client.pubKey) { + logger.warn("Client has no endpoint or listen port"); + return; + } + + const { siteId, chainId } = message.data; + + // Get the site + const [site] = await db + .select() + .from(sites) + .where(eq(sites.siteId, siteId)) + .limit(1); + + if (!site || !site.exitNodeId) { + logger.warn("Site not found or has no exit node"); + return; + } + + // update the peer on the newt + await newtUpdatePeer(siteId, client.pubKey, { + endpoint: "" // this removes the endpoint so the newt knows to accept local + }); + + // Just ack the message, we don't keep sending it + return { + message: { + type: "olm/wg/peer/local", + data: { + siteId: siteId, + chainId + } + }, + broadcast: false, + excludeSender: false + }; +}; diff --git a/server/routers/olm/handleOlmRelayMessage.ts b/server/routers/olm/handleOlmRelayMessage.ts index 7196824d2..406ed7bbb 100644 --- a/server/routers/olm/handleOlmRelayMessage.ts +++ b/server/routers/olm/handleOlmRelayMessage.ts @@ -79,9 +79,9 @@ export const handleOlmRelayMessage: MessageHandler = async (context) => { ) ); - // update the peer on the exit node + // update the peer on the newt await newtUpdatePeer(siteId, client.pubKey, { - endpoint: "" // this removes the endpoint so the exit node knows to relay + endpoint: "" // this removes the endpoint so the newt knows to relay }); return { diff --git a/server/routers/olm/handleOlmUnLocalMessage.ts b/server/routers/olm/handleOlmUnLocalMessage.ts new file mode 100644 index 000000000..55d312815 --- /dev/null +++ b/server/routers/olm/handleOlmUnLocalMessage.ts @@ -0,0 +1,95 @@ +import { db, exitNodes, sites } from "@server/db"; +import { MessageHandler } from "@server/routers/ws"; +import { clients, clientSitesAssociationsCache, Olm } from "@server/db"; +import { and, eq } from "drizzle-orm"; +import { updatePeer as newtUpdatePeer } from "../newt/peers"; +import logger from "@server/logger"; + +export const handleOlmUnLocalMessage: MessageHandler = async (context) => { + const { message, client: c, sendToClient } = context; + const olm = c as Olm; + + logger.info("Handling unlocal olm message!"); + + if (!olm) { + logger.warn("Olm not found"); + return; + } + + if (!olm.clientId) { + logger.warn("Olm has no client!"); + return; + } + + const clientId = olm.clientId; + + const [client] = await db + .select() + .from(clients) + .where(eq(clients.clientId, clientId)) + .limit(1); + + if (!client) { + logger.warn("Client not found"); + return; + } + + // make sure we hand endpoints for both the site and the client and the lastHolePunch is not too old + if (!client.pubKey) { + logger.warn("Client has no endpoint or listen port"); + return; + } + + const { siteId, chainId } = message.data; + + // Get the site + const [site] = await db + .select() + .from(sites) + .where(eq(sites.siteId, siteId)) + .limit(1); + + if (!site) { + logger.warn("Site not found or has no exit node"); + return; + } + + const [clientSiteAssociation] = await db + .select() + .from(clientSitesAssociationsCache) + .where( + and( + eq(clientSitesAssociationsCache.clientId, olm.clientId), + eq(clientSitesAssociationsCache.siteId, siteId) + ) + ); + + if (!clientSiteAssociation) { + logger.warn("Client-Site association not found"); + return; + } + + if (!clientSiteAssociation.endpoint) { + logger.warn("Client-Site association has no endpoint, cannot unrelay"); + return; + } + + // update the peer on the newt + await newtUpdatePeer(siteId, client.pubKey, { + endpoint: clientSiteAssociation.isRelayed + ? "" + : clientSiteAssociation.endpoint // this is the endpoint of the client to connect directly to the newt + }); + + return { + message: { + type: "olm/wg/peer/unlocal", + data: { + siteId: siteId, + chainId + } + }, + broadcast: false, + excludeSender: false + }; +}; diff --git a/server/routers/olm/handleOlmUnRelayMessage.ts b/server/routers/olm/handleOlmUnRelayMessage.ts index a7b426023..3f73a5834 100644 --- a/server/routers/olm/handleOlmUnRelayMessage.ts +++ b/server/routers/olm/handleOlmUnRelayMessage.ts @@ -77,9 +77,9 @@ export const handleOlmUnRelayMessage: MessageHandler = async (context) => { return; } - // update the peer on the exit node + // update the peer on the newt await newtUpdatePeer(siteId, client.pubKey, { - endpoint: clientSiteAssociation.endpoint // this is the endpoint of the client to connect directly to the exit node + endpoint: clientSiteAssociation.endpoint // this is the endpoint of the client to connect directly to the newt }); return { diff --git a/server/routers/olm/index.ts b/server/routers/olm/index.ts index 5c151a8cf..e11d4e48e 100644 --- a/server/routers/olm/index.ts +++ b/server/routers/olm/index.ts @@ -13,3 +13,5 @@ export * from "./recoverOlmWithFingerprint"; export * from "./handleOlmDisconnectingMessage"; export * from "./handleOlmServerInitAddPeerHandshake"; export * from "./offlineChecker"; +export * from "./handleOlmUnLocalMessage"; +export * from "./handleOlmLocalMessage"; diff --git a/server/routers/ws/messageHandlers.ts b/server/routers/ws/messageHandlers.ts index f89284389..496002142 100644 --- a/server/routers/ws/messageHandlers.ts +++ b/server/routers/ws/messageHandlers.ts @@ -20,7 +20,9 @@ import { handleOlmServerPeerAddMessage, handleOlmUnRelayMessage, handleOlmDisconnectingMessage, - handleOlmServerInitAddPeerHandshake + handleOlmServerInitAddPeerHandshake, + handleOlmLocalMessage, + handleOlmUnLocalMessage } from "../olm"; import { handleHealthcheckStatusMessage } from "../target"; import { handleRoundTripMessage } from "./handleRoundTripMessage"; @@ -32,6 +34,8 @@ export const messageHandlers: Record = { "olm/wg/register": handleOlmRegisterMessage, "olm/wg/relay": handleOlmRelayMessage, "olm/wg/unrelay": handleOlmUnRelayMessage, + "olm/wg/local": handleOlmLocalMessage, + "olm/wg/unlocal": handleOlmUnLocalMessage, "olm/ping": handleOlmPingMessage, "olm/disconnecting": handleOlmDisconnectingMessage, "newt/disconnecting": handleNewtDisconnectingMessage,