UNPKG

@cloudpss/ubrpc

Version:

Rpc server/client build on websocket and ubjson.

60 lines (57 loc) 2.56 kB
import type { WebSocket } from '@cloudpss/fetch'; import type { ConnectionID, RpcMetadata } from './types/payload.js'; import { decodePayload, deserializeError } from './utils/serialize.js'; import { VERSION } from './version.js'; const AUTH_TIMEOUT = 5000; /** 接受认证消息 */ export async function waitAuth( socket: WebSocket, seq?: number, id?: ConnectionID, ): Promise<[seq: number, id: ConnectionID, meta: RpcMetadata]> { return new Promise((resolve, reject) => { const isResponse = seq != null && id != null; const timeout = setTimeout(() => { reject(new Error(`Failed to authenticate, no ${isResponse ? 'response' : 'request'} in ${AUTH_TIMEOUT}ms`)); finalize(); }, AUTH_TIMEOUT); const handleMessage = (ev: MessageEvent): void => { try { const payload = decodePayload(ev.data); if (!payload || payload.type !== 'auth') { if (isResponse) return reject(new Error(`Failed to authenticate, bad response from server`)); else return reject(new Error(`Failed to authenticate, bad request from client`)); } if (payload.version !== VERSION) { return reject( new Error( `Failed to authenticate, version not match, expected ${VERSION}, got ${payload.version}`, ), ); } if (isResponse) { if (payload.seq !== seq) { return reject(new Error(`Failed to authenticate, bad response seq from server`)); } if (payload.id !== id) { return reject(new Error(`Failed to authenticate, bad response id from server`)); } } if (payload.error) { return reject(deserializeError(payload.error)); } const metadata = typeof payload.metadata != 'object' ? {} : (payload.metadata ?? {}); resolve([payload.seq, payload.id, metadata]); } catch (ex) { reject(ex as Error); } finally { finalize(); } }; const finalize = (): void => { clearTimeout(timeout); socket.removeEventListener('message', handleMessage); }; socket.addEventListener('message', handleMessage, { once: true }); }); }