@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.
Files changed (80) hide show
  1. package/lib/browser/ws-channel-handler.d.ts +1 -10
  2. package/lib/browser/ws-channel-handler.d.ts.map +1 -1
  3. package/lib/browser/ws-channel-handler.js +22 -11
  4. package/lib/browser/ws-channel-handler.js.map +1 -1
  5. package/lib/common/connection/drivers/simple.d.ts +7 -7
  6. package/lib/common/connection/drivers/simple.d.ts.map +1 -1
  7. package/lib/common/connection/drivers/simple.js.map +1 -1
  8. package/lib/common/index.d.ts +0 -4
  9. package/lib/common/index.d.ts.map +1 -1
  10. package/lib/common/index.js +0 -4
  11. package/lib/common/index.js.map +1 -1
  12. package/lib/common/rpc/connection.d.ts +3 -4
  13. package/lib/common/rpc/connection.d.ts.map +1 -1
  14. package/lib/common/rpc/connection.js +30 -14
  15. package/lib/common/rpc/connection.js.map +1 -1
  16. package/lib/common/rpc/message-io.d.ts +11 -54
  17. package/lib/common/rpc/message-io.d.ts.map +1 -1
  18. package/lib/common/rpc/message-io.js +10 -63
  19. package/lib/common/rpc/message-io.js.map +1 -1
  20. package/lib/common/rpc/multiplexer.d.ts +0 -2
  21. package/lib/common/rpc/multiplexer.d.ts.map +1 -1
  22. package/lib/common/rpc/multiplexer.js +2 -6
  23. package/lib/common/rpc/multiplexer.js.map +1 -1
  24. package/lib/common/rpc-service/index.d.ts +0 -1
  25. package/lib/common/rpc-service/index.d.ts.map +1 -1
  26. package/lib/common/rpc-service/index.js +0 -1
  27. package/lib/common/rpc-service/index.js.map +1 -1
  28. package/lib/common/rpc-service/registry.d.ts +2 -2
  29. package/lib/common/rpc-service/registry.d.ts.map +1 -1
  30. package/lib/common/rpc-service/registry.js +0 -6
  31. package/lib/common/rpc-service/registry.js.map +1 -1
  32. package/lib/common/server-handler.d.ts +1 -7
  33. package/lib/common/server-handler.d.ts.map +1 -1
  34. package/lib/common/server-handler.js +11 -13
  35. package/lib/common/server-handler.js.map +1 -1
  36. package/lib/common/ws-channel.d.ts +201 -11
  37. package/lib/common/ws-channel.d.ts.map +1 -1
  38. package/lib/common/ws-channel.js +85 -49
  39. package/lib/common/ws-channel.js.map +1 -1
  40. package/package.json +5 -5
  41. package/src/browser/ws-channel-handler.ts +26 -29
  42. package/src/common/connection/drivers/simple.ts +5 -5
  43. package/src/common/index.ts +0 -4
  44. package/src/common/rpc/connection.ts +36 -19
  45. package/src/common/rpc/message-io.ts +10 -123
  46. package/src/common/rpc/multiplexer.ts +3 -12
  47. package/src/common/rpc-service/index.ts +0 -1
  48. package/src/common/rpc-service/registry.ts +2 -10
  49. package/src/common/server-handler.ts +26 -24
  50. package/src/common/ws-channel.ts +207 -72
  51. package/lib/common/channel/index.d.ts +0 -2
  52. package/lib/common/channel/index.d.ts.map +0 -1
  53. package/lib/common/channel/index.js +0 -5
  54. package/lib/common/channel/index.js.map +0 -1
  55. package/lib/common/channel/types.d.ts +0 -66
  56. package/lib/common/channel/types.d.ts.map +0 -1
  57. package/lib/common/channel/types.js +0 -8
  58. package/lib/common/channel/types.js.map +0 -1
  59. package/lib/common/serializer/fury.d.ts +0 -122
  60. package/lib/common/serializer/fury.d.ts.map +0 -1
  61. package/lib/common/serializer/fury.js +0 -51
  62. package/lib/common/serializer/fury.js.map +0 -1
  63. package/lib/common/serializer/index.d.ts +0 -6
  64. package/lib/common/serializer/index.d.ts.map +0 -1
  65. package/lib/common/serializer/index.js +0 -21
  66. package/lib/common/serializer/index.js.map +0 -1
  67. package/lib/common/serializer/raw.d.ts +0 -4
  68. package/lib/common/serializer/raw.d.ts.map +0 -1
  69. package/lib/common/serializer/raw.js +0 -8
  70. package/lib/common/serializer/raw.js.map +0 -1
  71. package/lib/common/serializer/types.d.ts +0 -5
  72. package/lib/common/serializer/types.d.ts.map +0 -1
  73. package/lib/common/serializer/types.js +0 -3
  74. package/lib/common/serializer/types.js.map +0 -1
  75. package/src/common/channel/index.ts +0 -1
  76. package/src/common/channel/types.ts +0 -82
  77. package/src/common/serializer/fury.ts +0 -61
  78. package/src/common/serializer/index.ts +0 -23
  79. package/src/common/serializer/raw.ts +0 -8
  80. 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 { IConnectionShape } from '../common/connection/types';
7
- import { ISerializer, furySerializer, wrapSerializer } from '../common/serializer';
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: ILogger = console;
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
- public connection: IRuntimeSocketConnection<Uint8Array>,
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.channelMap.forEach((channel) => {
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.wrappedConnection.onMessage((msg) => {
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.wrappedConnection, {
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<T = Uint8Array> extends BaseConnection<T> {
5
+ export class SimpleConnection extends BaseConnection<Uint8Array> {
6
6
  constructor(
7
7
  public options: {
8
- send?: (data: T) => void;
9
- onMessage?: (cb: (data: T) => void) => IDisposable;
8
+ send?: (data: Uint8Array) => void;
9
+ onMessage?: (cb: (data: Uint8Array) => void) => IDisposable;
10
10
  } = {},
11
11
  ) {
12
12
  super();
13
13
  }
14
- send(data: T): void {
14
+ send(data: Uint8Array): void {
15
15
  this.options.send?.(data);
16
16
  }
17
- onMessage(cb: (data: T) => void): IDisposable {
17
+ onMessage(cb: (data: Uint8Array) => void): IDisposable {
18
18
  if (this.options.onMessage) {
19
19
  return this.options.onMessage(cb);
20
20
  }
@@ -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 { BaseMessageIO, MessageIO, OperationType, RPCErrorMessage, RPCResponseMessage } from './message-io';
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: BaseMessageIO;
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
- const message = this.io.readMessage(data);
201
- const opType = message.kind;
202
- const requestId = message.requestId;
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(this._timeoutHandles.get(requestId));
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 { headers, method } = message;
213
- const err = (message as RPCErrorMessage).error;
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 { method, headers, args } = message;
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 { parseError, stringifyError } from '@opensumi/ide-core-common/lib/utils';
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
- Error,
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 interface RPCRequestMessage {
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.Error);
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, MessageIO } from './message-io';
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,5 @@
1
1
  export * from './stub';
2
2
  export * from './center';
3
- export * from './registry';
4
3
 
5
4
  export abstract class RPCService<T = any> {
6
5
  rpcClient?: T[];
@@ -1,6 +1,6 @@
1
1
  import { DisposableStore, Emitter, IDisposable } from '@opensumi/ide-core-common';
2
2
 
3
- import { BaseMessageIO, TSumiProtocol, TSumiProtocolMethod } from '../rpc';
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: BaseMessageIO) {
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 { WSChannel, WSServerChannel } from './ws-channel';
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
- serializer: ISerializer<ChannelMessage, any> = furySerializer;
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(wrappedConnection, { id, clientId, logger: this.logger });
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
- wrappedConnection.onMessage((msg: ChannelMessage) => {
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
- wrappedConnection.send({
167
- kind: 'error',
168
- id,
169
- code: ErrorMessageCode.ChannelNotFound,
170
- message: `channel ${id} not found`,
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
  }