From 6b18cd787b962dc2d0a1e63299eb03f37aa1621b Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Tue, 4 Mar 2025 14:33:21 -0500 Subject: [PATCH] await dial permissions (#893) --- sdk/nodejs1/sdk/src/zrok/ziti.ts | 51 +++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/sdk/nodejs1/sdk/src/zrok/ziti.ts b/sdk/nodejs1/sdk/src/zrok/ziti.ts index 6948e436..9332e88c 100644 --- a/sdk/nodejs1/sdk/src/zrok/ziti.ts +++ b/sdk/nodejs1/sdk/src/zrok/ziti.ts @@ -20,11 +20,60 @@ export const listener = (shr: Share, ziti.listen(shr.shareToken, 0, listenCallback, listenClientCallback, clientConnectCallback, clientDataCallback); } -export const dialer = (acc: Access, connectCallback: any, dataCallback: any): ziti.dialer => { +export const dialer = async (acc: Access, connectCallback: any, dataCallback: any): ziti.dialer => { ziti.ziti_services_refresh(); + await awaitDialPermissions(acc.shareToken); ziti.dial(acc.shareToken, false, connectCallback, dataCallback); } export const write = (conn: any, buf: any, writeCallback: any = () => {}) => { ziti.write(conn, buf, writeCallback); } + +export enum ServicePermissions { + None = 0, + Bind = 2, + Dial = 3, +} + +export class ServiceStatus { + status: number | undefined; + permissions: ServicePermissions | undefined; + + constructor(status: number | undefined, permissions: ServicePermissions | undefined) { + this.status = status; + this.permissions = permissions; + } +} + +const awaitDialPermissions = async (shareToken: string) => { + let serviceStatus: ServiceStatus; + const startTime = process.hrtime(); + return new Promise((resolve: (value: any) => void, reject: (reason?: any) => void) => { + (async function waitForPermission() { + serviceStatus = await serviceAvailable(shareToken); + if(serviceStatus.status !== 0) { + throw new Error("shareToken '" + shareToken + "' not present in network"); + } + if(serviceStatus.permissions !== ServicePermissions.Dial) { + const now = process.hrtime(startTime); + const elapsedTimeInMs = now[0] * 1000 + now[1] / 1000000; + if(elapsedTimeInMs > 30 * 1000) { + return reject("timeout waiting for shareToken '" + shareToken + "' to acquire dial permissions"); + } + setTimeout(waitForPermission, 100); + } else { + return resolve(0); + } + })(); + }); +} + +const serviceAvailable = async (serviceName: string): Promise => { + return new Promise((resolve) => { + ziti.ziti_service_available(serviceName, (status: any) => { + const serviceStatus = new ServiceStatus(status.status, status.permissions); + resolve(serviceStatus); + }) + }); +} \ No newline at end of file