@cloudgaming/rpc
Advanced tools
Comparing version 1.5.1 to 1.6.0
@@ -7,2 +7,3 @@ import { RpcClientObject, FunctionName, FunctionPayload, FunctionResult } from './types'; | ||
sessionId: string; | ||
enableKeepAlive: boolean; | ||
private sequence; | ||
@@ -16,5 +17,9 @@ private retryTimeout; | ||
private baseEndpoint; | ||
private keepAliveTimer; | ||
private connectTimes; | ||
constructor(endpoint: string, type?: string); | ||
connect(authToken?: string, skipAuth?: boolean): Promise<void>; | ||
private _connect; | ||
disconnect(): Promise<void>; | ||
private keepAlive; | ||
setHandler<T extends FunctionName>(fn: T, handler: (param: FunctionPayload[T]) => Promise<FunctionResult[T]>): void; | ||
@@ -26,2 +31,3 @@ private readonly handleMessage; | ||
onClose: any; | ||
onReconnect: any; | ||
private reconnect; | ||
@@ -28,0 +34,0 @@ private rpcCall; |
@@ -9,5 +9,7 @@ "use strict"; | ||
const nanoid = require("nanoid"); | ||
const debug = debug_1.default('rpc:client'); | ||
const debug = (0, debug_1.default)('rpc:client'); | ||
const RETRY_TIMEOUT_BASE = 1000; | ||
const CONNECT_TIMEOUT = 10000; | ||
const KEEPALIVE_INTERVAL = 27000; | ||
const KEEPALIVE_TIMEOUT = 3000; | ||
class Client extends class { | ||
@@ -18,2 +20,4 @@ } { | ||
super(); | ||
this.enableKeepAlive = false; | ||
this.connectTimes = 0; | ||
this.handleMessage = async (msg) => { | ||
@@ -24,3 +28,3 @@ if (!(msg.data instanceof Blob)) { | ||
} | ||
const data = wrap_1.parseData(new Uint8Array(await readBlobAsArrayBuffer(msg.data))); | ||
const data = (0, wrap_1.parseData)(new Uint8Array(await readBlobAsArrayBuffer(msg.data))); | ||
const { request, response } = data; | ||
@@ -41,3 +45,3 @@ if (request) { | ||
if (!Object.prototype.hasOwnProperty.call(this.rpcHandlers, request.n)) { | ||
console.error('handler not found for function: ' + functionKey); | ||
console.error(`[RPC] handler not found for function: ${functionKey}`); | ||
return; | ||
@@ -52,3 +56,3 @@ } | ||
else { | ||
const buf = wrap_1.buildResponse(request.s, 200, result); | ||
const buf = (0, wrap_1.buildResponse)(request.s, 200, result); | ||
this.websocket.send(buf); | ||
@@ -63,3 +67,3 @@ } | ||
else { | ||
const buf = wrap_1.buildError(request.s, 500, e.message); | ||
const buf = (0, wrap_1.buildError)(request.s, 500, e.message); | ||
this.websocket.send(buf); | ||
@@ -106,2 +110,6 @@ } | ||
}; | ||
// triggers on reconnect (in case of error or server close) | ||
this.onReconnect = () => { | ||
// for override | ||
}; | ||
this.type = type; | ||
@@ -121,2 +129,9 @@ this.baseEndpoint = endpoint; | ||
async connect(authToken, skipAuth) { | ||
await this._connect(authToken, skipAuth); | ||
if (this.enableKeepAlive) { | ||
await this.keepAlive(); | ||
} | ||
} | ||
// used in both reconnect and connect | ||
async _connect(authToken, skipAuth) { | ||
if (skipAuth !== true && this.skipAuth !== true) { | ||
@@ -154,2 +169,3 @@ if (!authToken && !this.authToken) { | ||
debug('connected'); | ||
this.connectTimes++; | ||
this.retryTimeout = RETRY_TIMEOUT_BASE; | ||
@@ -185,14 +201,52 @@ resolve(); | ||
this.websocket.removeEventListener('close', this.handleClose); | ||
clearTimeout(this.keepAliveTimer); | ||
const ws = this.websocket; | ||
this.websocket = null; | ||
this.generateSessionId(); | ||
return new Promise(resolve => { | ||
ws.close(); | ||
if (ws.readyState === ws.CLOSED) { | ||
resolve(); | ||
await waitForClose(ws); | ||
} | ||
async keepAlive() { | ||
if (!this.enableKeepAlive) { | ||
return; | ||
} | ||
try { | ||
if (this.websocket.readyState !== this.websocket.OPEN) { | ||
debug('websocket is not open, no keepalive will sent'); | ||
return; | ||
} | ||
else { | ||
ws.addEventListener('close', () => resolve()); | ||
} | ||
}); | ||
debug('sending keepalive ping'); | ||
await new Promise((resolve, reject) => { | ||
const timer = setTimeout(() => { | ||
debug('keepalive timeout'); | ||
reject(new Error('ping timeout')); | ||
}, KEEPALIVE_TIMEOUT); | ||
this.Ping({}) | ||
.catch(e => { | ||
if (e.message.match(/Method p not found\./)) { | ||
return; | ||
} | ||
else { | ||
throw e; | ||
} | ||
}) | ||
.then(() => { | ||
debug('keepalive ok'); | ||
clearTimeout(timer); | ||
resolve(); | ||
}) | ||
.catch(e => { | ||
debug('keepalive server error', e); | ||
clearTimeout(timer); | ||
reject(e); | ||
}); | ||
}); | ||
} | ||
catch { | ||
debug('keepalive failed, try to reconnect'); | ||
await this.reconnect(); | ||
} | ||
finally { | ||
clearTimeout(this.keepAliveTimer); | ||
this.keepAliveTimer = setTimeout(() => void this.keepAlive(), KEEPALIVE_INTERVAL); | ||
} | ||
} | ||
@@ -205,3 +259,4 @@ setHandler(fn, handler) { | ||
this.websocket = null; | ||
await this.connect(); | ||
await this._connect(); | ||
this.onReconnect(); | ||
} | ||
@@ -223,3 +278,3 @@ catch (e) { | ||
debug('request', 'method', methodName, 'params', param, 'seq', seq); | ||
const request = wrap_1.buildRequest(methodName, seq, param); | ||
const request = (0, wrap_1.buildRequest)(methodName, seq, param); | ||
const d = { | ||
@@ -259,2 +314,12 @@ resolve: null, | ||
} | ||
function waitForClose(ws) { | ||
return new Promise(resolve => { | ||
if (ws.readyState === ws.CLOSED) { | ||
resolve(); | ||
} | ||
else { | ||
ws.addEventListener('close', () => resolve()); | ||
} | ||
}); | ||
} | ||
//# sourceMappingURL=Client.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
@@ -10,3 +14,3 @@ if (k2 === undefined) k2 = k; | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p); | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
@@ -13,0 +17,0 @@ Object.defineProperty(exports, "__esModule", { value: true }); |
/// <reference types="node" /> | ||
export declare enum FunctionName { | ||
/** any -> any, ping */ | ||
Ping = "p", | ||
/** client->server, auth connection */ | ||
@@ -31,3 +33,3 @@ Auth = "a", | ||
ForceStop = "fs", | ||
/** agent -> server */ | ||
/** agent->server */ | ||
AgentReportBasicInfo = "arbi", | ||
@@ -72,3 +74,3 @@ /** agent->server, auth */ | ||
PortableInstall = "pi", | ||
/** server->agent */ | ||
/** server->agent, agent->server, server->client, client->server */ | ||
Relay = "relay", | ||
@@ -85,2 +87,3 @@ /** server->agent */ | ||
export declare type FunctionPayload = { | ||
[FunctionName.Ping]: Record<string, never>; | ||
[FunctionName.Auth]: { | ||
@@ -90,4 +93,4 @@ /** auth token */ | ||
}; | ||
[FunctionName.AuthFlowWeb]: {}; | ||
[FunctionName.AuthFlowSuccess]: {}; | ||
[FunctionName.AuthFlowWeb]: Record<string, never>; | ||
[FunctionName.AuthFlowSuccess]: Record<string, never>; | ||
[FunctionName.GetDatacenterList]: { | ||
@@ -158,3 +161,3 @@ /** game name */ | ||
}; | ||
[FunctionName.GetCurrentCredits]: {}; | ||
[FunctionName.GetCurrentCredits]: Record<string, never>; | ||
[FunctionName.AboutToStop]: { | ||
@@ -206,3 +209,3 @@ /** code */ | ||
}; | ||
[FunctionName.LicenseSteamQueryGuard]: {}; | ||
[FunctionName.LicenseSteamQueryGuard]: Record<string, never>; | ||
[FunctionName.LicenseSteamUpdateSentry]: { | ||
@@ -227,3 +230,3 @@ sentries: Array<{ | ||
}; | ||
[FunctionName.AgentDisconnectSession]: {}; | ||
[FunctionName.AgentDisconnectSession]: Record<string, never>; | ||
[FunctionName.MountVhd]: { | ||
@@ -304,2 +307,3 @@ src: string; | ||
export declare type FunctionResult = { | ||
[FunctionName.Ping]: Record<string, never>; | ||
[FunctionName.Auth]: any; | ||
@@ -306,0 +310,0 @@ [FunctionName.AuthFlowWeb]: { |
@@ -6,2 +6,4 @@ "use strict"; | ||
(function (FunctionName) { | ||
/** any -> any, ping */ | ||
FunctionName["Ping"] = "p"; | ||
/** client->server, auth connection */ | ||
@@ -35,3 +37,3 @@ FunctionName["Auth"] = "a"; | ||
FunctionName["ForceStop"] = "fs"; | ||
/** agent -> server */ | ||
/** agent->server */ | ||
FunctionName["AgentReportBasicInfo"] = "arbi"; | ||
@@ -76,3 +78,3 @@ /** agent->server, auth */ | ||
FunctionName["PortableInstall"] = "pi"; | ||
/** server->agent */ | ||
/** server->agent, agent->server, server->client, client->server */ | ||
FunctionName["Relay"] = "relay"; | ||
@@ -79,0 +81,0 @@ /** server->agent */ |
@@ -11,3 +11,3 @@ "use strict"; | ||
}; | ||
return msgpack_1.encode(request); | ||
return (0, msgpack_1.encode)(request); | ||
} | ||
@@ -21,3 +21,3 @@ exports.buildRequest = buildRequest; | ||
}; | ||
return msgpack_1.encode(response); | ||
return (0, msgpack_1.encode)(response); | ||
} | ||
@@ -32,15 +32,15 @@ exports.buildResponse = buildResponse; | ||
}; | ||
return msgpack_1.encode(response); | ||
return (0, msgpack_1.encode)(response); | ||
} | ||
exports.buildError = buildError; | ||
function parseRequest(data) { | ||
return msgpack_1.decode(data); | ||
return (0, msgpack_1.decode)(data); | ||
} | ||
exports.parseRequest = parseRequest; | ||
function parseResponse(data) { | ||
return msgpack_1.decode(data); | ||
return (0, msgpack_1.decode)(data); | ||
} | ||
exports.parseResponse = parseResponse; | ||
function parseData(data) { | ||
const raw = msgpack_1.decode(data); | ||
const raw = (0, msgpack_1.decode)(data); | ||
if (raw.c) { | ||
@@ -47,0 +47,0 @@ return { response: raw, raw }; |
{ | ||
"name": "@cloudgaming/rpc", | ||
"version": "1.5.1", | ||
"version": "1.6.0", | ||
"main": "dist/index.js", | ||
@@ -15,3 +15,3 @@ "type": "commonjs", | ||
"build": "tsc", | ||
"watch": "tsc --watch --preserveWatchOutput", | ||
"watch": "tsc --watch --preserveWatchOutput --module esnext", | ||
"lint": "eslint . --ext .js,.jsx,.ts,.tsx", | ||
@@ -18,0 +18,0 @@ "clean": "rimraf dist", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
58164
949