xshell 0.0.57 → 0.0.59
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/net.browser.d.ts +51 -38
- package/net.browser.js +126 -120
- package/net.browser.js.map +1 -1
- package/net.d.ts +51 -38
- package/net.js +131 -122
- package/net.js.map +1 -1
- package/package.json +27 -28
- package/process.d.ts +6 -0
- package/process.js.map +1 -1
- package/prototype.browser.d.ts +8 -8
- package/prototype.browser.js.map +1 -1
- package/prototype.d.ts +20 -16
- package/prototype.js +17 -12
- package/prototype.js.map +1 -1
- package/repl.d.ts +1 -1
- package/repl.js +10 -10
- package/repl.js.map +1 -1
- package/server.js.map +1 -1
- package/utils.browser.d.ts +12 -2
- package/utils.browser.js +35 -7
- package/utils.browser.js.map +1 -1
- package/utils.d.ts +13 -3
- package/utils.js +26 -3
- package/utils.js.map +1 -1
package/net.d.ts
CHANGED
|
@@ -81,6 +81,12 @@ export declare function rpc(func: string, args?: any[], { url, async: _async, ig
|
|
|
81
81
|
async?: boolean;
|
|
82
82
|
ignore?: boolean;
|
|
83
83
|
}): Promise<any>;
|
|
84
|
+
/** 连接 websocket url, 设置各种事件监听器
|
|
85
|
+
- url
|
|
86
|
+
- options:
|
|
87
|
+
- on_message: 根据 websocket frame 的 opcode 不同 (text frame 或 binary frame) event 中的 data 对应为 ArrayBuffer 或者 string
|
|
88
|
+
https://datatracker.ietf.org/doc/html/rfc6455#section-5.2
|
|
89
|
+
*/
|
|
84
90
|
export declare function connect_websocket(url: string | URL, { protocols, max_payload, // 8 GB
|
|
85
91
|
on_open, on_close, on_error, on_message }: {
|
|
86
92
|
protocols?: string | string[];
|
|
@@ -92,73 +98,80 @@ on_open, on_close, on_error, on_message }: {
|
|
|
92
98
|
}, websocket: WebSocket): any;
|
|
93
99
|
on_error?(event: any, websocket: WebSocket): any;
|
|
94
100
|
on_message(event: {
|
|
95
|
-
data: ArrayBuffer;
|
|
101
|
+
data: ArrayBuffer | string;
|
|
96
102
|
}, websocket: WebSocket): any;
|
|
97
103
|
}): Promise<WebSocket>;
|
|
104
|
+
/** 接收到消息后的处理函数
|
|
105
|
+
返回值可以是:
|
|
106
|
+
- 数组: 会自动被封装为 { id: 相同, data: 返回值, done: true } 这样的消息并调用 websocket.send 将其发送
|
|
107
|
+
- void: 什么都不做
|
|
108
|
+
- 以上的 promise
|
|
109
|
+
*/
|
|
110
|
+
export declare type MessageHandler = (message: Message, websocket?: WebSocket) => void | any[] | Promise<void | any[]>;
|
|
98
111
|
/** 二进制消息格式
|
|
99
112
|
- json.length (小端序): 4 字节
|
|
100
113
|
- json 数据
|
|
101
114
|
- binary 数据
|
|
102
115
|
*/
|
|
103
|
-
export interface Message<
|
|
104
|
-
/**
|
|
116
|
+
export interface Message<TData extends any[] = any[]> {
|
|
117
|
+
/** rpc id: 在 rpc 系统中认为是唯一的。用来在单个 websocket 连接上复用多个 rpc 请求。多个相同 id 的 message 组成一个请求流 */
|
|
105
118
|
id?: number;
|
|
106
|
-
/** rpc
|
|
119
|
+
/** 只在 rpc 发起时指定被调用的 function name,发起时 rpc 时必传 */
|
|
107
120
|
func?: string;
|
|
108
|
-
/**
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
|
|
121
|
+
/** 通过这个 flag 主动表明这是发往对方的最后一个 message, 对方可以销毁 handler 了
|
|
122
|
+
并非强制,可以不说明,由双方的函数自己约定
|
|
123
|
+
*/
|
|
124
|
+
done?: boolean;
|
|
125
|
+
/** 通知对方这里产生的错误 */
|
|
126
|
+
error?: Error;
|
|
127
|
+
/** data 是一个数组, 作为:
|
|
114
128
|
- rpc 发起方调用 func 的参数,或者请求流 message 携带的数据
|
|
115
|
-
-
|
|
129
|
+
- 结果或者响应流的数据,传给请求发起方
|
|
130
|
+
|
|
131
|
+
里面是可序列化为 json 的 js 变量,或者是 Uint8Array
|
|
132
|
+
Uint8Array 的参数处理后被替换为 Uint8Array.byteLength, 并将下标记录在 bins 中
|
|
116
133
|
*/
|
|
117
|
-
|
|
118
|
-
/** bins:
|
|
134
|
+
data?: TData;
|
|
135
|
+
/** bins: data 中哪些下标对应的原始值是 Uint8Array 类型的,如: [0, 3] */
|
|
119
136
|
bins?: number[];
|
|
120
|
-
/** 被调方执行 func 产生的错误 */
|
|
121
|
-
error?: Error;
|
|
122
|
-
/** 如果请求或者响应是一个流,通过这个 flag 表明是最后一个 message, 并且可以销毁 handler 了 */
|
|
123
|
-
done?: boolean;
|
|
124
137
|
}
|
|
125
|
-
/** 通过创建
|
|
138
|
+
/** 通过创建 remote 对象对 websocket rpc 进行抽象
|
|
126
139
|
调用方使用 remote.call 进行调用
|
|
127
|
-
被调方在创建
|
|
140
|
+
被调方在创建 remote 对象时传入 funcs 注册处理函数,并使用 remote.handle 方法处理 websocket message
|
|
141
|
+
未连接时自动连接,断开后自动重连
|
|
128
142
|
*/
|
|
129
143
|
export declare class Remote {
|
|
130
144
|
url: string;
|
|
131
|
-
websocket
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
funcs: Record<string,
|
|
135
|
-
/**
|
|
136
|
-
handlers:
|
|
145
|
+
/** 主动发起 websocket 连接的客户端 (构造函数传 url) 有这个属性 */
|
|
146
|
+
websocket?: WebSocket;
|
|
147
|
+
/** 通过 rpc message.func 被调用的 rpc 函数 */
|
|
148
|
+
funcs: Record<string, MessageHandler>;
|
|
149
|
+
/** map<id, message handler>: 通过 rpc message.id 找到对应的 handler, unary rpc 接收方不需要设置 handlers, 发送方需要 */
|
|
150
|
+
handlers: Map<number, MessageHandler>;
|
|
137
151
|
print: boolean;
|
|
138
|
-
/** 在未连接时或连接断开后,调用 call 是否自动连接到 remote */
|
|
139
|
-
autoconnect: boolean;
|
|
140
152
|
pconnect: Promise<any>;
|
|
141
153
|
get connected(): boolean;
|
|
142
|
-
static parse<
|
|
143
|
-
static pack({ id, func,
|
|
144
|
-
constructor({ url, funcs, websocket
|
|
154
|
+
static parse<TData extends any[] = any[]>(array_buffer: ArrayBuffer): Message<TData>;
|
|
155
|
+
static pack({ id, func, data, done, error }: Message): Uint8Array;
|
|
156
|
+
constructor({ url, funcs, websocket }?: {
|
|
145
157
|
url?: string;
|
|
146
158
|
funcs?: Remote['funcs'];
|
|
147
159
|
websocket?: WebSocket;
|
|
148
|
-
autoconnect?: boolean;
|
|
149
160
|
});
|
|
161
|
+
/** 幂等,保证 websocket 已连接,否则抛出异常,不需要手动调用,在其它方法中已默认自动重连 */
|
|
150
162
|
connect(): Promise<void>;
|
|
151
163
|
disconnect(): void;
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
如果为 unary rpc, 可以不传 handler, await call 之后可以得到响应 message 的 args
|
|
164
|
+
/** 接收 websocket 连接的 remote 端必传 websocket 参数;发起端选传,如果传了必须等于 this.websocket
|
|
165
|
+
发送或连接出错时自动清理 message.id 对应的 handler
|
|
155
166
|
*/
|
|
156
|
-
|
|
157
|
-
/** 处理接收到的
|
|
158
|
-
|
|
159
|
-
|
|
167
|
+
send(message: Message, websocket?: WebSocket): Promise<void>;
|
|
168
|
+
/** 处理接收到的 websocket message 并解析, 根据 id dispatch 到对应的 handler 进行处理
|
|
169
|
+
如果 message.done == true 则清理 handler
|
|
170
|
+
如果 handler 返回了值,则包装为 message 发送
|
|
160
171
|
*/
|
|
161
172
|
handle(event: {
|
|
162
173
|
data: ArrayBuffer;
|
|
163
174
|
}, websocket: WebSocket): Promise<void>;
|
|
175
|
+
/** 调用 remote 中的 func, 只适用于最简单的一元 rpc (请求, 响应) */
|
|
176
|
+
call<TReturn extends any[] = any[]>(func: string, args?: any[]): Promise<TReturn>;
|
|
164
177
|
}
|
package/net.js
CHANGED
|
@@ -6,7 +6,7 @@ import iconv from 'iconv-lite';
|
|
|
6
6
|
import qs from 'qs';
|
|
7
7
|
import { Cookie, MemoryCookieStore } from 'tough-cookie';
|
|
8
8
|
import './prototype.js';
|
|
9
|
-
import { inspect, output_width, concat } from './utils.js';
|
|
9
|
+
import { inspect, output_width, concat, assert, genid } from './utils.js';
|
|
10
10
|
export var MyProxy;
|
|
11
11
|
(function (MyProxy) {
|
|
12
12
|
MyProxy["socks5"] = "http://localhost:10080";
|
|
@@ -84,7 +84,7 @@ export async function request(url, { queries, body, type = 'application/json', p
|
|
|
84
84
|
resolveWithFullResponse: true,
|
|
85
85
|
headers: {
|
|
86
86
|
'accept-language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,ja-JP;q=0.6,ja;q=0.5',
|
|
87
|
-
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/
|
|
87
|
+
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36',
|
|
88
88
|
...body ? { 'content-type': type } : {},
|
|
89
89
|
...cookies ? {
|
|
90
90
|
cookie: Object.entries(cookies)
|
|
@@ -247,23 +247,38 @@ export async function rpc(func, args, { url = 'http://localhost:8421/api/rpc', a
|
|
|
247
247
|
}
|
|
248
248
|
let decoder = new TextDecoder();
|
|
249
249
|
let encoder = new TextEncoder();
|
|
250
|
+
/** 连接 websocket url, 设置各种事件监听器
|
|
251
|
+
- url
|
|
252
|
+
- options:
|
|
253
|
+
- on_message: 根据 websocket frame 的 opcode 不同 (text frame 或 binary frame) event 中的 data 对应为 ArrayBuffer 或者 string
|
|
254
|
+
https://datatracker.ietf.org/doc/html/rfc6455#section-5.2
|
|
255
|
+
*/
|
|
250
256
|
export async function connect_websocket(url, { protocols, max_payload = 2 ** 33, // 8 GB
|
|
251
257
|
on_open, on_close, on_error, on_message }) {
|
|
252
|
-
let websocket = new WebSocket(url, protocols, {
|
|
258
|
+
let websocket = new WebSocket(url, protocols, {
|
|
259
|
+
maxPayload: max_payload,
|
|
260
|
+
skipUTF8Validation: true
|
|
261
|
+
});
|
|
253
262
|
// https://stackoverflow.com/questions/11821096/what-is-the-difference-between-an-arraybuffer-and-a-blob/39951543
|
|
254
263
|
websocket.binaryType = 'arraybuffer';
|
|
255
264
|
return new Promise((resolve, reject) => {
|
|
256
265
|
websocket.addEventListener('open', async (event) => {
|
|
257
|
-
console.log(
|
|
266
|
+
console.log(new Date().toLocaleTimeString() + ': ' +
|
|
267
|
+
'websocket connected: ' +
|
|
268
|
+
(protocols ?
|
|
269
|
+
typeof protocols === 'string' ? `protocol: ${protocols}, url: ` : `protocol: [${protocols.join(', ')}], url: `
|
|
270
|
+
:
|
|
271
|
+
'') +
|
|
272
|
+
websocket.url);
|
|
258
273
|
await on_open?.(event, websocket);
|
|
259
274
|
resolve(websocket);
|
|
260
275
|
});
|
|
261
276
|
websocket.addEventListener('close', event => {
|
|
262
|
-
console.log(`${
|
|
277
|
+
console.log(`${new Date().toLocaleTimeString()}: websocket closed: url: ${websocket.url}, code: ${event.code}, reason: ${event.reason}`);
|
|
263
278
|
on_close?.(event, websocket);
|
|
264
279
|
});
|
|
265
280
|
websocket.addEventListener('error', event => {
|
|
266
|
-
const message = `${websocket.url}
|
|
281
|
+
const message = `${new Date().toLocaleTimeString()} websocket errored: ${websocket.url}`;
|
|
267
282
|
on_error?.(event, websocket);
|
|
268
283
|
reject(Object.assign(new Error(message), { event }));
|
|
269
284
|
});
|
|
@@ -272,21 +287,20 @@ on_open, on_close, on_error, on_message }) {
|
|
|
272
287
|
});
|
|
273
288
|
});
|
|
274
289
|
}
|
|
275
|
-
/** 通过创建
|
|
290
|
+
/** 通过创建 remote 对象对 websocket rpc 进行抽象
|
|
276
291
|
调用方使用 remote.call 进行调用
|
|
277
|
-
被调方在创建
|
|
292
|
+
被调方在创建 remote 对象时传入 funcs 注册处理函数,并使用 remote.handle 方法处理 websocket message
|
|
293
|
+
未连接时自动连接,断开后自动重连
|
|
278
294
|
*/
|
|
279
295
|
export class Remote {
|
|
280
296
|
url;
|
|
297
|
+
/** 主动发起 websocket 连接的客户端 (构造函数传 url) 有这个属性 */
|
|
281
298
|
websocket;
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
handlers = [];
|
|
299
|
+
/** 通过 rpc message.func 被调用的 rpc 函数 */
|
|
300
|
+
funcs;
|
|
301
|
+
/** map<id, message handler>: 通过 rpc message.id 找到对应的 handler, unary rpc 接收方不需要设置 handlers, 发送方需要 */
|
|
302
|
+
handlers = new Map();
|
|
287
303
|
print = false;
|
|
288
|
-
/** 在未连接时或连接断开后,调用 call 是否自动连接到 remote */
|
|
289
|
-
autoconnect = true;
|
|
290
304
|
pconnect;
|
|
291
305
|
get connected() {
|
|
292
306
|
return this.websocket?.readyState === WebSocket.OPEN;
|
|
@@ -299,154 +313,149 @@ export class Remote {
|
|
|
299
313
|
let message = JSON.parse(decoder.decode(buf.subarray(4, offset)));
|
|
300
314
|
if (message.bins) {
|
|
301
315
|
const { bins } = message;
|
|
302
|
-
let {
|
|
316
|
+
let { data } = message;
|
|
303
317
|
for (const ibin of bins) {
|
|
304
|
-
const len_buf =
|
|
305
|
-
|
|
318
|
+
const len_buf = data[ibin];
|
|
319
|
+
data[ibin] = buf.subarray(offset, offset + len_buf);
|
|
306
320
|
offset += len_buf;
|
|
307
321
|
}
|
|
308
322
|
}
|
|
309
323
|
return message;
|
|
310
324
|
}
|
|
311
|
-
static pack({ id, func,
|
|
312
|
-
let
|
|
325
|
+
static pack({ id, func, data = [], done, error }) {
|
|
326
|
+
let data_ = new Array(data.length);
|
|
313
327
|
let bins = [];
|
|
314
328
|
let bufs = [];
|
|
315
|
-
for (let i = 0; i <
|
|
316
|
-
const
|
|
317
|
-
if (
|
|
329
|
+
for (let i = 0; i < data.length; i++) {
|
|
330
|
+
const item = data[i];
|
|
331
|
+
if (item instanceof Uint8Array) {
|
|
318
332
|
bins.push(i);
|
|
319
|
-
bufs.push(
|
|
320
|
-
|
|
333
|
+
bufs.push(item);
|
|
334
|
+
data_[i] = item.length;
|
|
321
335
|
}
|
|
336
|
+
else
|
|
337
|
+
data_[i] = item;
|
|
322
338
|
}
|
|
323
339
|
const data_json = {
|
|
324
340
|
id,
|
|
325
341
|
...func ? { func } : {},
|
|
326
|
-
...ignore ? { ignore } : {},
|
|
327
|
-
..._async ? { async: _async } : {},
|
|
328
342
|
...done ? { done } : {},
|
|
329
343
|
...error ? { error } : {},
|
|
330
|
-
...
|
|
344
|
+
...data_.length ? { data: data_ } : {},
|
|
331
345
|
...bins.length ? { bins } : {},
|
|
332
346
|
};
|
|
333
347
|
const str_json = encoder.encode(JSON.stringify(data_json));
|
|
334
348
|
let dv = new DataView(new ArrayBuffer(4));
|
|
335
349
|
dv.setUint32(0, str_json.length, true);
|
|
336
|
-
return concat([
|
|
337
|
-
dv,
|
|
338
|
-
str_json,
|
|
339
|
-
...bufs
|
|
340
|
-
]);
|
|
350
|
+
return concat([dv, str_json, ...bufs]);
|
|
341
351
|
}
|
|
342
|
-
constructor({ url, funcs, websocket
|
|
352
|
+
constructor({ url, funcs = {}, websocket } = {}) {
|
|
343
353
|
this.url = url;
|
|
344
|
-
|
|
345
|
-
this.funcs = funcs;
|
|
354
|
+
this.funcs = funcs;
|
|
346
355
|
this.websocket = websocket;
|
|
347
|
-
if (typeof autoconnect !== 'undefined')
|
|
348
|
-
this.autoconnect = autoconnect;
|
|
349
356
|
}
|
|
357
|
+
/** 幂等,保证 websocket 已连接,否则抛出异常,不需要手动调用,在其它方法中已默认自动重连 */
|
|
350
358
|
async connect() {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
359
|
+
if (this.connected)
|
|
360
|
+
return;
|
|
361
|
+
const ptail = this.pconnect;
|
|
362
|
+
let resolve;
|
|
363
|
+
this.pconnect = new Promise((_resolve, _reject) => {
|
|
364
|
+
resolve = _resolve;
|
|
357
365
|
});
|
|
366
|
+
await ptail;
|
|
367
|
+
try {
|
|
368
|
+
if (!this.connected)
|
|
369
|
+
// 保存的 rpc 状态在 this.handlers, 与 websocket 无关,因此即使断开重连也不影响 rpc 的运行,即
|
|
370
|
+
// 底层连接断开后自动重连对上层应该是无感知的,除非再次连接时失败
|
|
371
|
+
this.websocket = await connect_websocket(this.url, { on_message: this.handle.bind(this) });
|
|
372
|
+
}
|
|
373
|
+
finally {
|
|
374
|
+
resolve();
|
|
375
|
+
}
|
|
358
376
|
}
|
|
359
377
|
disconnect() {
|
|
360
378
|
this.websocket?.close();
|
|
361
|
-
this.id = 0;
|
|
362
|
-
this.handlers = [];
|
|
363
|
-
}
|
|
364
|
-
send(message, websocket = this.websocket) {
|
|
365
|
-
if (websocket?.readyState !== WebSocket.OPEN)
|
|
366
|
-
throw new Error(`${websocket?.url || 'websocket'} 已断开,无法调用 remote.send`);
|
|
367
|
-
if (!('id' in message))
|
|
368
|
-
message.id = this.id;
|
|
369
|
-
websocket.send(Remote.pack(message));
|
|
370
379
|
}
|
|
371
|
-
/**
|
|
372
|
-
|
|
380
|
+
/** 接收 websocket 连接的 remote 端必传 websocket 参数;发起端选传,如果传了必须等于 this.websocket
|
|
381
|
+
发送或连接出错时自动清理 message.id 对应的 handler
|
|
373
382
|
*/
|
|
374
|
-
async
|
|
375
|
-
|
|
376
|
-
if (this.
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
this.pconnect = new Promise((_resolve, _reject) => {
|
|
381
|
-
resolve = _resolve;
|
|
382
|
-
});
|
|
383
|
-
try {
|
|
384
|
-
await ptail;
|
|
385
|
-
}
|
|
386
|
-
catch { }
|
|
387
|
-
// 临界区结束,只有一个 call 调用运行到这里,可以开始连接 WebSocket
|
|
388
|
-
if (!this.connected) {
|
|
389
|
-
if (this.websocket)
|
|
390
|
-
console.log(`${this.url} 已断开,尝试自动重连`);
|
|
391
|
-
else
|
|
392
|
-
console.log(`${this.url} 未连接,尝试自动连接`);
|
|
393
|
-
try {
|
|
394
|
-
await this.connect();
|
|
395
|
-
}
|
|
396
|
-
finally {
|
|
397
|
-
resolve();
|
|
398
|
-
}
|
|
399
|
-
}
|
|
383
|
+
async send(message, websocket) {
|
|
384
|
+
try {
|
|
385
|
+
if (this.url) {
|
|
386
|
+
assert(!websocket || websocket === this.websocket);
|
|
387
|
+
await this.connect();
|
|
388
|
+
websocket = this.websocket;
|
|
400
389
|
}
|
|
401
|
-
else
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
};
|
|
417
|
-
this.send(message);
|
|
418
|
-
this.id++;
|
|
419
|
-
});
|
|
390
|
+
else {
|
|
391
|
+
assert(websocket);
|
|
392
|
+
assert(!websocket.url, `The websocket received by the server should have no url attribute, websocket.url: ${websocket.url}`);
|
|
393
|
+
if (websocket.readyState !== WebSocket.OPEN)
|
|
394
|
+
throw new Error(`remote.send(): websocket client disconnected`);
|
|
395
|
+
}
|
|
396
|
+
if (!message.id)
|
|
397
|
+
message.id = genid();
|
|
398
|
+
websocket.send(Remote.pack(message));
|
|
399
|
+
}
|
|
400
|
+
catch (error) {
|
|
401
|
+
if (message.id)
|
|
402
|
+
this.handlers.delete(message.id);
|
|
403
|
+
throw error;
|
|
404
|
+
}
|
|
420
405
|
}
|
|
421
|
-
/** 处理接收到的
|
|
422
|
-
|
|
423
|
-
|
|
406
|
+
/** 处理接收到的 websocket message 并解析, 根据 id dispatch 到对应的 handler 进行处理
|
|
407
|
+
如果 message.done == true 则清理 handler
|
|
408
|
+
如果 handler 返回了值,则包装为 message 发送
|
|
424
409
|
*/
|
|
425
410
|
async handle(event, websocket) {
|
|
426
411
|
const message = Remote.parse(event.data);
|
|
427
|
-
const {
|
|
412
|
+
const { id, func, done } = message;
|
|
428
413
|
if (this.print)
|
|
429
414
|
console.log(message);
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
await handler(message, websocket);
|
|
436
|
-
}
|
|
437
|
-
catch (error) {
|
|
438
|
-
this.send({
|
|
439
|
-
id,
|
|
440
|
-
error,
|
|
441
|
-
done: true
|
|
442
|
-
}, websocket);
|
|
443
|
-
throw error;
|
|
444
|
-
}
|
|
445
|
-
else { // 作为发起方
|
|
446
|
-
this.handlers[id](message);
|
|
415
|
+
let handler;
|
|
416
|
+
if (func)
|
|
417
|
+
handler = this.funcs[func];
|
|
418
|
+
else {
|
|
419
|
+
handler = this.handlers.get(id);
|
|
447
420
|
if (done)
|
|
448
|
-
this.handlers
|
|
421
|
+
this.handlers.delete(id);
|
|
422
|
+
}
|
|
423
|
+
try {
|
|
424
|
+
if (handler) {
|
|
425
|
+
const data = await handler(message, websocket);
|
|
426
|
+
if (data)
|
|
427
|
+
await this.send({ id, data }, websocket);
|
|
428
|
+
}
|
|
429
|
+
else if (message.error)
|
|
430
|
+
throw Object.assign(new Error(), message.error);
|
|
431
|
+
else
|
|
432
|
+
throw new Error(`rpc handler not found: ${func ? `func: ${func.quote()}` : `id: ${id}`}`);
|
|
449
433
|
}
|
|
434
|
+
catch (error) {
|
|
435
|
+
if (websocket.readyState === WebSocket.OPEN &&
|
|
436
|
+
!message.error // 防止无限循环往对方发送 error, 只有在对方无错误时才可以发送
|
|
437
|
+
)
|
|
438
|
+
try {
|
|
439
|
+
await this.send({ id, error, done: true }, websocket);
|
|
440
|
+
}
|
|
441
|
+
catch { }
|
|
442
|
+
throw error;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
/** 调用 remote 中的 func, 只适用于最简单的一元 rpc (请求, 响应) */
|
|
446
|
+
async call(func, args) {
|
|
447
|
+
return new Promise(async (resolve, reject) => {
|
|
448
|
+
const id = genid();
|
|
449
|
+
this.handlers.set(id, (message) => {
|
|
450
|
+
const { error, data } = message;
|
|
451
|
+
if (error)
|
|
452
|
+
reject(Object.assign(new Error(), error));
|
|
453
|
+
else
|
|
454
|
+
resolve(data);
|
|
455
|
+
this.handlers.delete(id);
|
|
456
|
+
});
|
|
457
|
+
await this.send({ id, func, data: args }); // 不需要 done: true, 因为对面的 remote.handlers 中不会有这个 id 的 handler
|
|
458
|
+
});
|
|
450
459
|
}
|
|
451
460
|
}
|
|
452
461
|
//# sourceMappingURL=net.js.map
|