@opensumi/ide-connection 3.0.4-next-1716970216.0 → 3.0.4-next-1717045696.0
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/lib/browser/ws-channel-handler.d.ts +1 -10
- package/lib/browser/ws-channel-handler.d.ts.map +1 -1
- package/lib/browser/ws-channel-handler.js +22 -11
- package/lib/browser/ws-channel-handler.js.map +1 -1
- package/lib/common/connection/drivers/simple.d.ts +7 -7
- package/lib/common/connection/drivers/simple.d.ts.map +1 -1
- package/lib/common/connection/drivers/simple.js.map +1 -1
- package/lib/common/index.d.ts +0 -4
- package/lib/common/index.d.ts.map +1 -1
- package/lib/common/index.js +0 -4
- package/lib/common/index.js.map +1 -1
- package/lib/common/rpc/connection.d.ts +3 -4
- package/lib/common/rpc/connection.d.ts.map +1 -1
- package/lib/common/rpc/connection.js +30 -14
- package/lib/common/rpc/connection.js.map +1 -1
- package/lib/common/rpc/message-io.d.ts +11 -54
- package/lib/common/rpc/message-io.d.ts.map +1 -1
- package/lib/common/rpc/message-io.js +10 -63
- package/lib/common/rpc/message-io.js.map +1 -1
- package/lib/common/rpc/multiplexer.d.ts +0 -2
- package/lib/common/rpc/multiplexer.d.ts.map +1 -1
- package/lib/common/rpc/multiplexer.js +2 -6
- package/lib/common/rpc/multiplexer.js.map +1 -1
- package/lib/common/rpc-service/index.d.ts +0 -1
- package/lib/common/rpc-service/index.d.ts.map +1 -1
- package/lib/common/rpc-service/index.js +0 -1
- package/lib/common/rpc-service/index.js.map +1 -1
- package/lib/common/rpc-service/registry.d.ts +2 -2
- package/lib/common/rpc-service/registry.d.ts.map +1 -1
- package/lib/common/rpc-service/registry.js +0 -6
- package/lib/common/rpc-service/registry.js.map +1 -1
- package/lib/common/server-handler.d.ts +1 -7
- package/lib/common/server-handler.d.ts.map +1 -1
- package/lib/common/server-handler.js +11 -13
- package/lib/common/server-handler.js.map +1 -1
- package/lib/common/ws-channel.d.ts +201 -11
- package/lib/common/ws-channel.d.ts.map +1 -1
- package/lib/common/ws-channel.js +85 -49
- package/lib/common/ws-channel.js.map +1 -1
- package/package.json +5 -5
- package/src/browser/ws-channel-handler.ts +26 -29
- package/src/common/connection/drivers/simple.ts +5 -5
- package/src/common/index.ts +0 -4
- package/src/common/rpc/connection.ts +36 -19
- package/src/common/rpc/message-io.ts +10 -123
- package/src/common/rpc/multiplexer.ts +3 -12
- package/src/common/rpc-service/index.ts +0 -1
- package/src/common/rpc-service/registry.ts +2 -10
- package/src/common/server-handler.ts +26 -24
- package/src/common/ws-channel.ts +207 -72
- package/lib/common/channel/index.d.ts +0 -2
- package/lib/common/channel/index.d.ts.map +0 -1
- package/lib/common/channel/index.js +0 -5
- package/lib/common/channel/index.js.map +0 -1
- package/lib/common/channel/types.d.ts +0 -66
- package/lib/common/channel/types.d.ts.map +0 -1
- package/lib/common/channel/types.js +0 -8
- package/lib/common/channel/types.js.map +0 -1
- package/lib/common/serializer/fury.d.ts +0 -122
- package/lib/common/serializer/fury.d.ts.map +0 -1
- package/lib/common/serializer/fury.js +0 -51
- package/lib/common/serializer/fury.js.map +0 -1
- package/lib/common/serializer/index.d.ts +0 -6
- package/lib/common/serializer/index.d.ts.map +0 -1
- package/lib/common/serializer/index.js +0 -21
- package/lib/common/serializer/index.js.map +0 -1
- package/lib/common/serializer/raw.d.ts +0 -4
- package/lib/common/serializer/raw.d.ts.map +0 -1
- package/lib/common/serializer/raw.js +0 -8
- package/lib/common/serializer/raw.js.map +0 -1
- package/lib/common/serializer/types.d.ts +0 -5
- package/lib/common/serializer/types.d.ts.map +0 -1
- package/lib/common/serializer/types.js +0 -3
- package/lib/common/serializer/types.js.map +0 -1
- package/src/common/channel/index.ts +0 -1
- package/src/common/channel/types.ts +0 -82
- package/src/common/serializer/fury.ts +0 -61
- package/src/common/serializer/index.ts +0 -23
- package/src/common/serializer/raw.ts +0 -8
- package/src/common/serializer/types.ts +0 -4
|
@@ -1,17 +1,9 @@
|
|
|
1
1
|
import { EventEmitter } from '@opensumi/events';
|
|
2
2
|
import { Barrier, Deferred, DisposableStore, IReporterService, MultiMap, REPORT_NAME } from '@opensumi/ide-core-common';
|
|
3
3
|
|
|
4
|
-
import { ChannelMessage } from '../common/channel/types';
|
|
5
4
|
import { IRuntimeSocketConnection } from '../common/connection';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { ConnectionInfo, ILogger, WSCloseInfo } from '../common/types';
|
|
9
|
-
import { WSChannel } from '../common/ws-channel';
|
|
10
|
-
|
|
11
|
-
export interface WSChannelHandlerOptions {
|
|
12
|
-
logger?: ILogger;
|
|
13
|
-
channelSerializer?: ISerializer<ChannelMessage, any>;
|
|
14
|
-
}
|
|
5
|
+
import { ConnectionInfo, WSCloseInfo } from '../common/types';
|
|
6
|
+
import { ErrorMessageCode, WSChannel, parse, pingMessage } from '../common/ws-channel';
|
|
15
7
|
|
|
16
8
|
/**
|
|
17
9
|
* Channel Handler in browser
|
|
@@ -20,15 +12,13 @@ export class WSChannelHandler {
|
|
|
20
12
|
private _disposables = new DisposableStore();
|
|
21
13
|
|
|
22
14
|
private _onChannelCreatedEmitter = this._disposables.add(new EventEmitter<Record<string, [WSChannel]>>());
|
|
23
|
-
|
|
24
|
-
wrappedConnection: IConnectionShape<ChannelMessage>;
|
|
25
15
|
public onChannelCreated(path: string, listener: (channel: WSChannel) => void) {
|
|
26
16
|
return this._onChannelCreatedEmitter.on(path, listener);
|
|
27
17
|
}
|
|
28
18
|
|
|
29
19
|
private channelMap: Map<string, WSChannel> = new Map();
|
|
30
20
|
private channelCloseEventMap = new MultiMap<string, WSCloseInfo>();
|
|
31
|
-
private logger
|
|
21
|
+
private logger = console;
|
|
32
22
|
public clientId: string;
|
|
33
23
|
private heartbeatMessageTimer: NodeJS.Timeout | null;
|
|
34
24
|
private reporterService: IReporterService;
|
|
@@ -40,16 +30,10 @@ export class WSChannelHandler {
|
|
|
40
30
|
|
|
41
31
|
LOG_TAG: string;
|
|
42
32
|
|
|
43
|
-
constructor(
|
|
44
|
-
|
|
45
|
-
clientId: string,
|
|
46
|
-
options: WSChannelHandlerOptions = {},
|
|
47
|
-
) {
|
|
48
|
-
this.logger = options.logger || this.logger;
|
|
33
|
+
constructor(public connection: IRuntimeSocketConnection<Uint8Array>, logger: any, clientId: string) {
|
|
34
|
+
this.logger = logger || this.logger;
|
|
49
35
|
this.clientId = clientId;
|
|
50
36
|
this.LOG_TAG = `[WSChannelHandler] [client-id:${this.clientId}]`;
|
|
51
|
-
const serializer = options.channelSerializer || furySerializer;
|
|
52
|
-
this.wrappedConnection = wrapSerializer(this.connection, serializer);
|
|
53
37
|
}
|
|
54
38
|
// 为解决建立连接之后,替换成可落盘的 logger
|
|
55
39
|
replaceLogger(logger: any) {
|
|
@@ -65,24 +49,37 @@ export class WSChannelHandler {
|
|
|
65
49
|
clearTimeout(this.heartbeatMessageTimer);
|
|
66
50
|
}
|
|
67
51
|
this.heartbeatMessageTimer = global.setTimeout(() => {
|
|
68
|
-
this.
|
|
69
|
-
channel.ping();
|
|
70
|
-
});
|
|
71
|
-
|
|
52
|
+
this.connection.send(pingMessage);
|
|
72
53
|
this.heartbeatMessage();
|
|
73
54
|
}, 10 * 1000);
|
|
74
55
|
}
|
|
75
56
|
|
|
76
57
|
public async initHandler() {
|
|
77
|
-
this.
|
|
58
|
+
this.connection.onMessage((message) => {
|
|
78
59
|
// 一个心跳周期内如果有收到消息,则不需要再发送心跳
|
|
79
60
|
this.heartbeatMessage();
|
|
80
61
|
|
|
62
|
+
const msg = parse(message);
|
|
63
|
+
|
|
81
64
|
switch (msg.kind) {
|
|
82
65
|
case 'pong':
|
|
83
|
-
// pong
|
|
66
|
+
// pong 没有 msg.id, 且不需要分发, 不处理
|
|
67
|
+
break;
|
|
68
|
+
case 'error':
|
|
69
|
+
this.logger.error(this.LOG_TAG, `receive error: id: ${msg.id}, code: ${msg.code}, error: ${msg.message}`);
|
|
70
|
+
switch (msg.code) {
|
|
71
|
+
case ErrorMessageCode.ChannelNotFound:
|
|
72
|
+
if (this.channelMap.has(msg.id)) {
|
|
73
|
+
// 如果远程报错 channel 不存在但是本机存在,则重新打开
|
|
74
|
+
const channel = this.channelMap.get(msg.id)!;
|
|
75
|
+
if (channel.channelPath) {
|
|
76
|
+
channel.pause();
|
|
77
|
+
channel.open(channel.channelPath, this.clientId);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
84
82
|
break;
|
|
85
|
-
|
|
86
83
|
default: {
|
|
87
84
|
const channel = this.channelMap.get(msg.id);
|
|
88
85
|
if (channel) {
|
|
@@ -141,7 +138,7 @@ export class WSChannelHandler {
|
|
|
141
138
|
this.logger.log(this.LOG_TAG, `channel ${key} already exists, dispose it`);
|
|
142
139
|
}
|
|
143
140
|
|
|
144
|
-
const channel = new WSChannel(this.
|
|
141
|
+
const channel = new WSChannel(this.connection, {
|
|
145
142
|
id: key,
|
|
146
143
|
logger: this.logger,
|
|
147
144
|
ensureServerReady: true,
|
|
@@ -2,19 +2,19 @@ import { IDisposable } from '@opensumi/ide-core-common';
|
|
|
2
2
|
|
|
3
3
|
import { BaseConnection } from './base';
|
|
4
4
|
|
|
5
|
-
export class SimpleConnection
|
|
5
|
+
export class SimpleConnection extends BaseConnection<Uint8Array> {
|
|
6
6
|
constructor(
|
|
7
7
|
public options: {
|
|
8
|
-
send?: (data:
|
|
9
|
-
onMessage?: (cb: (data:
|
|
8
|
+
send?: (data: Uint8Array) => void;
|
|
9
|
+
onMessage?: (cb: (data: Uint8Array) => void) => IDisposable;
|
|
10
10
|
} = {},
|
|
11
11
|
) {
|
|
12
12
|
super();
|
|
13
13
|
}
|
|
14
|
-
send(data:
|
|
14
|
+
send(data: Uint8Array): void {
|
|
15
15
|
this.options.send?.(data);
|
|
16
16
|
}
|
|
17
|
-
onMessage(cb: (data:
|
|
17
|
+
onMessage(cb: (data: Uint8Array) => void): IDisposable {
|
|
18
18
|
if (this.options.onMessage) {
|
|
19
19
|
return this.options.onMessage(cb);
|
|
20
20
|
}
|
package/src/common/index.ts
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
export * from './rpc-service/proxy';
|
|
2
|
-
export * from './rpc-service';
|
|
3
2
|
export * from './rpc/multiplexer';
|
|
4
3
|
export * from './rpcProtocol';
|
|
5
4
|
export * from './capturer';
|
|
6
5
|
export * from './ws-channel';
|
|
7
6
|
export * from './connect';
|
|
8
7
|
export * from './types';
|
|
9
|
-
export * from './connection';
|
|
10
|
-
export * from './serializer';
|
|
11
|
-
export * from './channel';
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
DisposableStore,
|
|
6
6
|
IDisposable,
|
|
7
7
|
canceled,
|
|
8
|
+
parseError,
|
|
8
9
|
} from '@opensumi/ide-utils';
|
|
9
10
|
import { SumiReadableStream, isReadableStream, listenReadable } from '@opensumi/ide-utils/lib/stream';
|
|
10
11
|
|
|
@@ -14,8 +15,9 @@ import { METHOD_NOT_REGISTERED } from '../constants';
|
|
|
14
15
|
import { ILogger } from '../types';
|
|
15
16
|
|
|
16
17
|
import { MethodTimeoutError } from './errors';
|
|
17
|
-
import {
|
|
18
|
+
import { MessageIO, OperationType, Status } from './message-io';
|
|
18
19
|
import {
|
|
20
|
+
IRequestHeaders,
|
|
19
21
|
IResponseHeaders,
|
|
20
22
|
TGenericNotificationHandler,
|
|
21
23
|
TGenericRequestHandler,
|
|
@@ -36,8 +38,6 @@ export interface ISumiConnectionOptions {
|
|
|
36
38
|
* The name of the connection, used for debugging(and can see in opensumi-devtools).
|
|
37
39
|
*/
|
|
38
40
|
name?: string;
|
|
39
|
-
|
|
40
|
-
io?: BaseMessageIO;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
const chunkedResponseHeaders: IResponseHeaders = {
|
|
@@ -61,7 +61,7 @@ export class SumiConnection implements IDisposable {
|
|
|
61
61
|
|
|
62
62
|
protected activeRequestPool = new Map<number, SumiReadableStream<any>>();
|
|
63
63
|
|
|
64
|
-
public io
|
|
64
|
+
public io = new MessageIO();
|
|
65
65
|
protected logger: ILogger;
|
|
66
66
|
|
|
67
67
|
protected capturer: Capturer;
|
|
@@ -73,8 +73,6 @@ export class SumiConnection implements IDisposable {
|
|
|
73
73
|
this.logger = getDebugLogger();
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
this.io = options.io || new MessageIO();
|
|
77
|
-
|
|
78
76
|
this.capturer = new Capturer(options.name || 'sumi');
|
|
79
77
|
this.disposable.add(this.capturer);
|
|
80
78
|
}
|
|
@@ -195,28 +193,35 @@ export class SumiConnection implements IDisposable {
|
|
|
195
193
|
}
|
|
196
194
|
|
|
197
195
|
listen() {
|
|
196
|
+
const { reader } = this.io;
|
|
197
|
+
|
|
198
198
|
this.disposable.add(
|
|
199
199
|
this.socket.onMessage((data) => {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
200
|
+
reader.reset(data);
|
|
201
|
+
// skip version, currently only have version 1
|
|
202
|
+
reader.skip(1);
|
|
203
|
+
|
|
204
|
+
const opType = reader.uint8() as OperationType;
|
|
205
|
+
const requestId = reader.uint32();
|
|
203
206
|
|
|
204
207
|
if (this._timeoutHandles.has(requestId)) {
|
|
205
|
-
clearTimeout
|
|
208
|
+
// Ignore some jest test scenarios where clearTimeout is not defined.
|
|
209
|
+
if (typeof clearTimeout === 'function') {
|
|
210
|
+
// @ts-ignore
|
|
211
|
+
clearTimeout(this._timeoutHandles.get(requestId));
|
|
212
|
+
}
|
|
206
213
|
this._timeoutHandles.delete(requestId);
|
|
207
214
|
}
|
|
208
215
|
|
|
209
216
|
switch (opType) {
|
|
210
|
-
case OperationType.Error:
|
|
211
217
|
case OperationType.Response: {
|
|
212
|
-
const
|
|
213
|
-
const
|
|
214
|
-
const result = (message as RPCResponseMessage).result;
|
|
218
|
+
const method = reader.stringOfVarUInt32();
|
|
219
|
+
const status = reader.uint16();
|
|
215
220
|
|
|
216
221
|
const runCallback = (headers: IResponseHeaders, error?: any, result?: any) => {
|
|
217
222
|
const callback = this._callbacks.get(requestId);
|
|
218
223
|
if (!callback) {
|
|
219
|
-
this.logger.error(`Cannot find callback for request ${requestId}: ${method}`);
|
|
224
|
+
this.logger.error(`Cannot find callback for request ${requestId}: ${method}, status: ${status}`);
|
|
220
225
|
return;
|
|
221
226
|
}
|
|
222
227
|
|
|
@@ -225,6 +230,17 @@ export class SumiConnection implements IDisposable {
|
|
|
225
230
|
callback(headers, error, result);
|
|
226
231
|
};
|
|
227
232
|
|
|
233
|
+
const headers = this.io.responseHeadersSerializer.read();
|
|
234
|
+
let err: any;
|
|
235
|
+
let result: any;
|
|
236
|
+
if (status === Status.Err) {
|
|
237
|
+
// todo: move to processor
|
|
238
|
+
const content = reader.stringOfVarUInt32();
|
|
239
|
+
err = parseError(content);
|
|
240
|
+
} else {
|
|
241
|
+
result = this.io.getProcessor(method).readResponse();
|
|
242
|
+
}
|
|
243
|
+
|
|
228
244
|
if (headers && headers.chunked) {
|
|
229
245
|
let activeReq: SumiReadableStream<any>;
|
|
230
246
|
if (this.activeRequestPool.has(requestId)) {
|
|
@@ -259,7 +275,9 @@ export class SumiConnection implements IDisposable {
|
|
|
259
275
|
case OperationType.Notification:
|
|
260
276
|
// fall through
|
|
261
277
|
case OperationType.Request: {
|
|
262
|
-
const
|
|
278
|
+
const method = reader.stringOfVarUInt32();
|
|
279
|
+
const headers = this.io.requestHeadersSerializer.read() as IRequestHeaders;
|
|
280
|
+
const args = this.io.getProcessor(method).readRequest();
|
|
263
281
|
|
|
264
282
|
if (headers.cancelable) {
|
|
265
283
|
const tokenSource = new CancellationTokenSource();
|
|
@@ -303,17 +321,16 @@ export class SumiConnection implements IDisposable {
|
|
|
303
321
|
},
|
|
304
322
|
onEnd: () => {
|
|
305
323
|
this.socket.send(this.io.Response(requestId, method, chunkedResponseHeaders, null));
|
|
306
|
-
this._cancellationTokenSources.delete(requestId);
|
|
307
324
|
},
|
|
308
325
|
onError: (err) => {
|
|
309
326
|
this.socket.send(this.io.Error(requestId, method, chunkedResponseHeaders, err));
|
|
310
|
-
this._cancellationTokenSources.delete(requestId);
|
|
311
327
|
},
|
|
312
328
|
});
|
|
313
329
|
} else {
|
|
314
330
|
this.socket.send(this.io.Response(requestId, method, nullHeaders, result));
|
|
315
|
-
this._cancellationTokenSources.delete(requestId);
|
|
316
331
|
}
|
|
332
|
+
|
|
333
|
+
this._cancellationTokenSources.delete(requestId);
|
|
317
334
|
};
|
|
318
335
|
|
|
319
336
|
const onError = (err: Error) => {
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import Fury, { Serializer, Type, TypeDescription } from '@furyjs/fury';
|
|
2
2
|
import { generateSerializer } from '@furyjs/fury/dist/lib/gen';
|
|
3
|
-
import { PlatformBuffer } from '@furyjs/fury/dist/lib/platformBuffer';
|
|
4
3
|
import { BinaryReader, BinaryWriter } from '@furyjs/fury/dist/lib/type';
|
|
5
4
|
|
|
6
|
-
import {
|
|
5
|
+
import { stringifyError } from '@opensumi/ide-core-common/lib/utils';
|
|
7
6
|
|
|
8
7
|
import { AnySerializer, IObjectTransfer } from '../fury-extends/any';
|
|
9
8
|
import { furyFactory } from '../fury-extends/shared';
|
|
@@ -25,7 +24,11 @@ export enum OperationType {
|
|
|
25
24
|
Notification,
|
|
26
25
|
Response,
|
|
27
26
|
Cancel,
|
|
28
|
-
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export enum Status {
|
|
30
|
+
OK,
|
|
31
|
+
Err,
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
export const HeadersProto = {
|
|
@@ -42,7 +45,6 @@ const PacketPrefix = {
|
|
|
42
45
|
Notification: (OperationType.Notification << 8) | ProtoVersionV1,
|
|
43
46
|
Response: (OperationType.Response << 8) | ProtoVersionV1,
|
|
44
47
|
Cancel: (OperationType.Cancel << 8) | ProtoVersionV1,
|
|
45
|
-
Error: (OperationType.Error << 8) | ProtoVersionV1,
|
|
46
48
|
} as const;
|
|
47
49
|
|
|
48
50
|
class SumiProtocolSerializer implements IProtocolSerializer {
|
|
@@ -103,66 +105,7 @@ export class AnyProtocolSerializer implements IProtocolSerializer {
|
|
|
103
105
|
}
|
|
104
106
|
}
|
|
105
107
|
|
|
106
|
-
export
|
|
107
|
-
kind: OperationType.Request;
|
|
108
|
-
requestId: number;
|
|
109
|
-
method: string;
|
|
110
|
-
headers: IRequestHeaders;
|
|
111
|
-
args: any[];
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export interface RPCNotificationMessage {
|
|
115
|
-
kind: OperationType.Notification;
|
|
116
|
-
requestId: number;
|
|
117
|
-
method: string;
|
|
118
|
-
headers: IRequestHeaders;
|
|
119
|
-
args: any[];
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export interface RPCResponseMessage {
|
|
123
|
-
kind: OperationType.Response;
|
|
124
|
-
requestId: number;
|
|
125
|
-
method: string;
|
|
126
|
-
headers: Record<string, any>;
|
|
127
|
-
result: any;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export interface RPCErrorMessage {
|
|
131
|
-
kind: OperationType.Error;
|
|
132
|
-
requestId: number;
|
|
133
|
-
method: string;
|
|
134
|
-
headers: Record<string, any>;
|
|
135
|
-
error: any;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
export interface RPCCancelMessage {
|
|
139
|
-
kind: OperationType.Cancel;
|
|
140
|
-
requestId: number;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
export type RPCMessage =
|
|
144
|
-
| RPCRequestMessage
|
|
145
|
-
| RPCNotificationMessage
|
|
146
|
-
| RPCResponseMessage
|
|
147
|
-
| RPCErrorMessage
|
|
148
|
-
| RPCCancelMessage;
|
|
149
|
-
|
|
150
|
-
export abstract class BaseMessageIO<T = any> {
|
|
151
|
-
abstract loadProtocolMethod?(
|
|
152
|
-
methodProtocol: TSumiProtocolMethod,
|
|
153
|
-
options?: { nameConverter?: (str: string) => string },
|
|
154
|
-
): void;
|
|
155
|
-
|
|
156
|
-
abstract Request(requestId: number, method: string, headers: IRequestHeaders, args: any[]): T;
|
|
157
|
-
abstract Notification(requestId: number, method: string, headers: IRequestHeaders, args: any[]): T;
|
|
158
|
-
abstract Cancel(requestId: number): T;
|
|
159
|
-
abstract Response(requestId: number, method: string, headers: Record<string, any>, result: any): T;
|
|
160
|
-
abstract Error(requestId: number, method: string, headers: Record<string, any>, error: any): T;
|
|
161
|
-
|
|
162
|
-
abstract readMessage(data: T): RPCMessage;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
export class MessageIO extends BaseMessageIO<PlatformBuffer> {
|
|
108
|
+
export class MessageIO {
|
|
166
109
|
fury: Fury;
|
|
167
110
|
reader: BinaryReader;
|
|
168
111
|
writer: BinaryWriter;
|
|
@@ -175,7 +118,6 @@ export class MessageIO extends BaseMessageIO<PlatformBuffer> {
|
|
|
175
118
|
responseHeadersSerializer: Serializer<IResponseHeaders, IRequestHeaders>;
|
|
176
119
|
|
|
177
120
|
constructor() {
|
|
178
|
-
super();
|
|
179
121
|
const fury = furyFactory();
|
|
180
122
|
this.fury = fury.fury;
|
|
181
123
|
this.reader = fury.reader;
|
|
@@ -274,6 +216,7 @@ export class MessageIO extends BaseMessageIO<PlatformBuffer> {
|
|
|
274
216
|
writer.uint16(PacketPrefix.Response);
|
|
275
217
|
writer.uint32(requestId);
|
|
276
218
|
writer.stringOfVarUInt32(method);
|
|
219
|
+
writer.uint16(Status.OK);
|
|
277
220
|
this.responseHeadersSerializer.write(headers);
|
|
278
221
|
this.getProcessor(method).writeResponse(result);
|
|
279
222
|
|
|
@@ -284,69 +227,13 @@ export class MessageIO extends BaseMessageIO<PlatformBuffer> {
|
|
|
284
227
|
const { writer } = this;
|
|
285
228
|
writer.reset();
|
|
286
229
|
|
|
287
|
-
writer.uint16(PacketPrefix.
|
|
230
|
+
writer.uint16(PacketPrefix.Response);
|
|
288
231
|
writer.uint32(requestId);
|
|
289
232
|
writer.stringOfVarUInt32(method);
|
|
233
|
+
writer.uint16(Status.Err);
|
|
290
234
|
this.responseHeadersSerializer.write(headers);
|
|
291
235
|
writer.stringOfVarUInt32(stringifyError(error));
|
|
292
236
|
|
|
293
237
|
return writer.dump();
|
|
294
238
|
}
|
|
295
|
-
|
|
296
|
-
readMessage(data: PlatformBuffer): RPCMessage {
|
|
297
|
-
const { reader } = this;
|
|
298
|
-
reader.reset(data);
|
|
299
|
-
|
|
300
|
-
// skip version, currently only have version 1
|
|
301
|
-
reader.skip(1);
|
|
302
|
-
const opType = reader.uint8() as OperationType;
|
|
303
|
-
const requestId = reader.uint32();
|
|
304
|
-
|
|
305
|
-
switch (opType) {
|
|
306
|
-
case OperationType.Request:
|
|
307
|
-
case OperationType.Notification: {
|
|
308
|
-
const method = reader.stringOfVarUInt32();
|
|
309
|
-
const headers = this.requestHeadersSerializer.read() as IRequestHeaders;
|
|
310
|
-
const args = this.getProcessor(method).readRequest();
|
|
311
|
-
return {
|
|
312
|
-
kind: opType,
|
|
313
|
-
requestId,
|
|
314
|
-
method,
|
|
315
|
-
headers,
|
|
316
|
-
args,
|
|
317
|
-
};
|
|
318
|
-
}
|
|
319
|
-
case OperationType.Error: {
|
|
320
|
-
const method = reader.stringOfVarUInt32();
|
|
321
|
-
const headers = this.responseHeadersSerializer.read() as IResponseHeaders;
|
|
322
|
-
const error = parseError(reader.stringOfVarUInt32());
|
|
323
|
-
return {
|
|
324
|
-
kind: OperationType.Error,
|
|
325
|
-
requestId,
|
|
326
|
-
method,
|
|
327
|
-
headers,
|
|
328
|
-
error,
|
|
329
|
-
};
|
|
330
|
-
}
|
|
331
|
-
case OperationType.Response: {
|
|
332
|
-
const method = reader.stringOfVarUInt32();
|
|
333
|
-
const headers = this.responseHeadersSerializer.read() as IResponseHeaders;
|
|
334
|
-
const result = this.getProcessor(method).readResponse();
|
|
335
|
-
return {
|
|
336
|
-
kind: OperationType.Response,
|
|
337
|
-
requestId,
|
|
338
|
-
method,
|
|
339
|
-
headers,
|
|
340
|
-
result,
|
|
341
|
-
};
|
|
342
|
-
}
|
|
343
|
-
case OperationType.Cancel:
|
|
344
|
-
return {
|
|
345
|
-
kind: OperationType.Cancel,
|
|
346
|
-
requestId,
|
|
347
|
-
};
|
|
348
|
-
default:
|
|
349
|
-
throw new Error(`Unknown message type: ${opType}`);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
239
|
}
|
|
@@ -2,7 +2,7 @@ import { BaseConnection } from '../connection';
|
|
|
2
2
|
import { ExtObjectTransfer } from '../fury-extends/any';
|
|
3
3
|
|
|
4
4
|
import { ISumiConnectionOptions, SumiConnection } from './connection';
|
|
5
|
-
import { AnyProtocolSerializer
|
|
5
|
+
import { AnyProtocolSerializer } from './message-io';
|
|
6
6
|
import { TSumiProtocol } from './types';
|
|
7
7
|
|
|
8
8
|
export class ProxyIdentifier<T = any> {
|
|
@@ -34,12 +34,6 @@ export interface IRPCProtocol {
|
|
|
34
34
|
get<T>(identifier: ProxyIdentifier<T>): T;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
function createExtMessageIO() {
|
|
38
|
-
const io = new MessageIO();
|
|
39
|
-
io.setAnySerializer(new AnyProtocolSerializer(io.writer, io.reader, ExtObjectTransfer));
|
|
40
|
-
return io;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
37
|
/**
|
|
44
38
|
* A connection multiplexer that allows to register multiple local RPC services and to create proxies for them.
|
|
45
39
|
*/
|
|
@@ -63,16 +57,13 @@ export class SumiConnectionMultiplexer extends SumiConnection implements IRPCPro
|
|
|
63
57
|
protected readonly _locals: Map<string, any>;
|
|
64
58
|
protected readonly _proxies: Map<string, any>;
|
|
65
59
|
protected _knownProtocols: Record<string, TSumiProtocol>;
|
|
66
|
-
io: MessageIO;
|
|
67
60
|
|
|
68
61
|
constructor(protected socket: BaseConnection<Uint8Array>, protected options: ISumiMultiplexerConnectionOptions = {}) {
|
|
69
|
-
super(socket,
|
|
70
|
-
...options,
|
|
71
|
-
io: createExtMessageIO(),
|
|
72
|
-
});
|
|
62
|
+
super(socket, options);
|
|
73
63
|
this._locals = new Map();
|
|
74
64
|
this._proxies = new Map();
|
|
75
65
|
this._knownProtocols = options.knownProtocols || {};
|
|
66
|
+
this.io.setAnySerializer(new AnyProtocolSerializer(this.io.writer, this.io.reader, ExtObjectTransfer));
|
|
76
67
|
|
|
77
68
|
this.onRequestNotFound((rpcName: string, args: any[]) => this.invoke(rpcName, args));
|
|
78
69
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DisposableStore, Emitter, IDisposable } from '@opensumi/ide-core-common';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { MessageIO, TSumiProtocol, TSumiProtocolMethod } from '../rpc';
|
|
4
4
|
import { RPCServiceMethod } from '../types';
|
|
5
5
|
|
|
6
6
|
const skipMethods = new Set(['constructor']);
|
|
@@ -119,21 +119,13 @@ export class ProtocolRegistry {
|
|
|
119
119
|
this.emitter.fire(serviceNames);
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
applyTo(io:
|
|
123
|
-
if (!io.loadProtocolMethod) {
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
|
|
122
|
+
applyTo(io: MessageIO) {
|
|
127
123
|
for (const protocol of this.protocolMap.values()) {
|
|
128
124
|
io.loadProtocolMethod(protocol);
|
|
129
125
|
}
|
|
130
126
|
|
|
131
127
|
this._disposables.add(
|
|
132
128
|
this.onProtocolUpdate((methods) => {
|
|
133
|
-
if (!io.loadProtocolMethod) {
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
129
|
for (const method of methods) {
|
|
138
130
|
const protocol = this.protocolMap.get(method);
|
|
139
131
|
if (protocol) {
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import { ChannelMessage, ErrorMessageCode } from './channel/types';
|
|
2
1
|
import { IConnectionShape } from './connection/types';
|
|
3
|
-
import { furySerializer, wrapSerializer } from './serializer';
|
|
4
|
-
import { ISerializer } from './serializer/types';
|
|
5
2
|
import { ILogger } from './types';
|
|
6
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
ChannelMessage,
|
|
5
|
+
ErrorMessageCode,
|
|
6
|
+
WSChannel,
|
|
7
|
+
WSServerChannel,
|
|
8
|
+
parse,
|
|
9
|
+
pongMessage,
|
|
10
|
+
stringify,
|
|
11
|
+
} from './ws-channel';
|
|
7
12
|
|
|
8
13
|
export interface IPathHandler {
|
|
9
14
|
dispose: (channel: WSChannel, connectionId: string) => void;
|
|
@@ -100,21 +105,12 @@ export class CommonChannelPathHandler {
|
|
|
100
105
|
|
|
101
106
|
export const commonChannelPathHandler = new CommonChannelPathHandler();
|
|
102
107
|
|
|
103
|
-
export interface ChannelHandlerOptions {
|
|
104
|
-
serializer?: ISerializer<ChannelMessage, any>;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
108
|
export abstract class BaseCommonChannelHandler {
|
|
108
109
|
protected channelMap: Map<string, WSServerChannel> = new Map();
|
|
109
110
|
|
|
110
111
|
protected heartbeatTimer: NodeJS.Timeout | null = null;
|
|
111
112
|
|
|
112
|
-
|
|
113
|
-
constructor(public handlerId: string, protected logger: ILogger = console, options: ChannelHandlerOptions = {}) {
|
|
114
|
-
if (options.serializer) {
|
|
115
|
-
this.serializer = options.serializer;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
113
|
+
constructor(public handlerId: string, protected logger: ILogger = console) {}
|
|
118
114
|
|
|
119
115
|
abstract doHeartbeat(connection: any): void;
|
|
120
116
|
|
|
@@ -133,20 +129,24 @@ export abstract class BaseCommonChannelHandler {
|
|
|
133
129
|
let clientId: string;
|
|
134
130
|
this.heartbeat(connection);
|
|
135
131
|
|
|
136
|
-
const wrappedConnection = wrapSerializer(connection, this.serializer);
|
|
137
|
-
|
|
138
132
|
const getOrCreateChannel = (id: string, clientId: string) => {
|
|
139
133
|
let channel = this.channelMap.get(id);
|
|
140
134
|
if (!channel) {
|
|
141
|
-
channel = new WSServerChannel(
|
|
135
|
+
channel = new WSServerChannel(connection, { id, clientId, logger: this.logger });
|
|
142
136
|
this.channelMap.set(id, channel);
|
|
143
137
|
}
|
|
144
138
|
return channel;
|
|
145
139
|
};
|
|
146
140
|
|
|
147
|
-
|
|
141
|
+
connection.onMessage((data: Uint8Array) => {
|
|
142
|
+
let msg: ChannelMessage;
|
|
148
143
|
try {
|
|
144
|
+
msg = parse(data);
|
|
145
|
+
|
|
149
146
|
switch (msg.kind) {
|
|
147
|
+
case 'ping':
|
|
148
|
+
connection.send(pongMessage);
|
|
149
|
+
break;
|
|
150
150
|
case 'open': {
|
|
151
151
|
const { id, path, connectionToken } = msg;
|
|
152
152
|
clientId = msg.clientId;
|
|
@@ -163,12 +163,14 @@ export abstract class BaseCommonChannelHandler {
|
|
|
163
163
|
if (channel) {
|
|
164
164
|
channel.dispatch(msg);
|
|
165
165
|
} else {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
166
|
+
connection.send(
|
|
167
|
+
stringify({
|
|
168
|
+
kind: 'error',
|
|
169
|
+
id,
|
|
170
|
+
code: ErrorMessageCode.ChannelNotFound,
|
|
171
|
+
message: `channel ${id} not found`,
|
|
172
|
+
}),
|
|
173
|
+
);
|
|
172
174
|
|
|
173
175
|
this.logger.warn(`channel ${id} is not found`);
|
|
174
176
|
}
|