@opensumi/ide-connection 3.0.4 → 3.0.5-next-1717466130.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 +10 -1
- package/lib/browser/ws-channel-handler.d.ts.map +1 -1
- package/lib/browser/ws-channel-handler.js +11 -22
- package/lib/browser/ws-channel-handler.js.map +1 -1
- package/lib/common/channel/index.d.ts +2 -0
- package/lib/common/channel/index.d.ts.map +1 -0
- package/lib/common/channel/index.js +5 -0
- package/lib/common/channel/index.js.map +1 -0
- package/lib/common/channel/types.d.ts +66 -0
- package/lib/common/channel/types.d.ts.map +1 -0
- package/lib/common/channel/types.js +8 -0
- package/lib/common/channel/types.js.map +1 -0
- 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 +4 -0
- package/lib/common/index.d.ts.map +1 -1
- package/lib/common/index.js +4 -0
- package/lib/common/index.js.map +1 -1
- package/lib/common/rpc/connection.d.ts +5 -4
- package/lib/common/rpc/connection.d.ts.map +1 -1
- package/lib/common/rpc/connection.js +21 -37
- package/lib/common/rpc/connection.js.map +1 -1
- package/lib/common/rpc/message-io.d.ts +62 -11
- package/lib/common/rpc/message-io.d.ts.map +1 -1
- package/lib/common/rpc/message-io.js +111 -10
- package/lib/common/rpc/message-io.js.map +1 -1
- package/lib/common/rpc/multiplexer.d.ts +11 -11
- package/lib/common/rpc/multiplexer.d.ts.map +1 -1
- package/lib/common/rpc/multiplexer.js +18 -17
- package/lib/common/rpc/multiplexer.js.map +1 -1
- package/lib/common/rpc-service/index.d.ts +1 -0
- package/lib/common/rpc-service/index.d.ts.map +1 -1
- package/lib/common/rpc-service/index.js +1 -0
- package/lib/common/rpc-service/index.js.map +1 -1
- package/lib/common/rpc-service/proxy/json.d.ts.map +1 -1
- package/lib/common/rpc-service/proxy/json.js +2 -2
- package/lib/common/rpc-service/proxy/json.js.map +1 -1
- package/lib/common/rpc-service/proxy/sumi.d.ts.map +1 -1
- package/lib/common/rpc-service/proxy/sumi.js +2 -2
- package/lib/common/rpc-service/proxy/sumi.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 +6 -0
- package/lib/common/rpc-service/registry.js.map +1 -1
- package/lib/common/serializer/fury.d.ts +122 -0
- package/lib/common/serializer/fury.d.ts.map +1 -0
- package/lib/common/serializer/fury.js +51 -0
- package/lib/common/serializer/fury.js.map +1 -0
- package/lib/common/serializer/index.d.ts +7 -0
- package/lib/common/serializer/index.d.ts.map +1 -0
- package/lib/common/serializer/index.js +22 -0
- package/lib/common/serializer/index.js.map +1 -0
- package/lib/common/serializer/raw.d.ts +4 -0
- package/lib/common/serializer/raw.d.ts.map +1 -0
- package/lib/common/serializer/raw.js +8 -0
- package/lib/common/serializer/raw.js.map +1 -0
- package/lib/common/serializer/types.d.ts +5 -0
- package/lib/common/serializer/types.d.ts.map +1 -0
- package/lib/common/serializer/types.js +3 -0
- package/lib/common/serializer/types.js.map +1 -0
- package/lib/common/server-handler.d.ts +7 -1
- package/lib/common/server-handler.d.ts.map +1 -1
- package/lib/common/server-handler.js +13 -11
- package/lib/common/server-handler.js.map +1 -1
- package/lib/common/ws-channel.d.ts +10 -202
- package/lib/common/ws-channel.d.ts.map +1 -1
- package/lib/common/ws-channel.js +40 -92
- package/lib/common/ws-channel.js.map +1 -1
- package/package.json +5 -5
- package/src/browser/ws-channel-handler.ts +29 -26
- package/src/common/channel/index.ts +1 -0
- package/src/common/channel/types.ts +82 -0
- package/src/common/connection/drivers/simple.ts +5 -5
- package/src/common/index.ts +4 -0
- package/src/common/rpc/connection.ts +28 -44
- package/src/common/rpc/message-io.ts +172 -10
- package/src/common/rpc/multiplexer.ts +27 -29
- package/src/common/rpc-service/index.ts +1 -0
- package/src/common/rpc-service/proxy/json.ts +13 -11
- package/src/common/rpc-service/proxy/sumi.ts +5 -3
- package/src/common/rpc-service/registry.ts +10 -2
- package/src/common/serializer/fury.ts +61 -0
- package/src/common/serializer/index.ts +24 -0
- package/src/common/serializer/raw.ts +8 -0
- package/src/common/serializer/types.ts +4 -0
- package/src/common/server-handler.ts +24 -26
- package/src/common/ws-channel.ts +63 -225
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DisposableStore, Emitter, IDisposable } from '@opensumi/ide-core-common';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { IMessageIO, TSumiProtocol, TSumiProtocolMethod } from '../rpc';
|
|
4
4
|
import { RPCServiceMethod } from '../types';
|
|
5
5
|
|
|
6
6
|
const skipMethods = new Set(['constructor']);
|
|
@@ -119,13 +119,21 @@ export class ProtocolRegistry {
|
|
|
119
119
|
this.emitter.fire(serviceNames);
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
applyTo(io:
|
|
122
|
+
applyTo(io: IMessageIO) {
|
|
123
|
+
if (!io.loadProtocolMethod) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
123
127
|
for (const protocol of this.protocolMap.values()) {
|
|
124
128
|
io.loadProtocolMethod(protocol);
|
|
125
129
|
}
|
|
126
130
|
|
|
127
131
|
this._disposables.add(
|
|
128
132
|
this.onProtocolUpdate((methods) => {
|
|
133
|
+
if (!io.loadProtocolMethod) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
129
137
|
for (const method of methods) {
|
|
130
138
|
const protocol = this.protocolMap.get(method);
|
|
131
139
|
if (protocol) {
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Type } from '@furyjs/fury';
|
|
2
|
+
|
|
3
|
+
import { ChannelMessage } from '../channel/types';
|
|
4
|
+
import { oneOf } from '../fury-extends/one-of';
|
|
5
|
+
|
|
6
|
+
import { ISerializer } from './types';
|
|
7
|
+
|
|
8
|
+
export const PingProtocol = Type.object('ping', {
|
|
9
|
+
id: Type.string(),
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export const PongProtocol = Type.object('pong', {
|
|
13
|
+
id: Type.string(),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export const OpenProtocol = Type.object('open', {
|
|
17
|
+
clientId: Type.string(),
|
|
18
|
+
id: Type.string(),
|
|
19
|
+
path: Type.string(),
|
|
20
|
+
connectionToken: Type.string(),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export const ServerReadyProtocol = Type.object('server-ready', {
|
|
24
|
+
id: Type.string(),
|
|
25
|
+
token: Type.string(),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export const ErrorProtocol = Type.object('error', {
|
|
29
|
+
id: Type.string(),
|
|
30
|
+
code: Type.uint16(),
|
|
31
|
+
message: Type.string(),
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
export const DataProtocol = Type.object('data', {
|
|
35
|
+
id: Type.string(),
|
|
36
|
+
content: Type.string(),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
export const BinaryProtocol = Type.object('binary', {
|
|
40
|
+
id: Type.string(),
|
|
41
|
+
binary: Type.binary(),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
export const CloseProtocol = Type.object('close', {
|
|
45
|
+
id: Type.string(),
|
|
46
|
+
code: Type.uint32(),
|
|
47
|
+
reason: Type.string(),
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const serializer = oneOf([
|
|
51
|
+
PingProtocol,
|
|
52
|
+
PongProtocol,
|
|
53
|
+
OpenProtocol,
|
|
54
|
+
ServerReadyProtocol,
|
|
55
|
+
DataProtocol,
|
|
56
|
+
BinaryProtocol,
|
|
57
|
+
CloseProtocol,
|
|
58
|
+
ErrorProtocol,
|
|
59
|
+
]);
|
|
60
|
+
|
|
61
|
+
export const furySerializer: ISerializer<ChannelMessage, Uint8Array> = serializer;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { IConnectionShape } from '../connection/types';
|
|
2
|
+
|
|
3
|
+
import { ISerializer } from './types';
|
|
4
|
+
|
|
5
|
+
export * from './fury';
|
|
6
|
+
export * from './raw';
|
|
7
|
+
export * from './types';
|
|
8
|
+
|
|
9
|
+
export const wrapSerializer = <FROM, TO>(
|
|
10
|
+
connection: IConnectionShape<TO>,
|
|
11
|
+
serializer: ISerializer<FROM, TO>,
|
|
12
|
+
): IConnectionShape<FROM> => ({
|
|
13
|
+
onceClose(cb) {
|
|
14
|
+
return connection.onceClose(cb);
|
|
15
|
+
},
|
|
16
|
+
onMessage(cb) {
|
|
17
|
+
return connection.onMessage((data) => {
|
|
18
|
+
cb(serializer.deserialize(data));
|
|
19
|
+
});
|
|
20
|
+
},
|
|
21
|
+
send(data) {
|
|
22
|
+
connection.send(serializer.serialize(data));
|
|
23
|
+
},
|
|
24
|
+
});
|
|
@@ -1,14 +1,9 @@
|
|
|
1
|
+
import { ChannelMessage, ErrorMessageCode } from './channel/types';
|
|
1
2
|
import { IConnectionShape } from './connection/types';
|
|
3
|
+
import { furySerializer, wrapSerializer } from './serializer';
|
|
4
|
+
import { ISerializer } from './serializer/types';
|
|
2
5
|
import { ILogger } from './types';
|
|
3
|
-
import {
|
|
4
|
-
ChannelMessage,
|
|
5
|
-
ErrorMessageCode,
|
|
6
|
-
WSChannel,
|
|
7
|
-
WSServerChannel,
|
|
8
|
-
parse,
|
|
9
|
-
pongMessage,
|
|
10
|
-
stringify,
|
|
11
|
-
} from './ws-channel';
|
|
6
|
+
import { WSChannel, WSServerChannel } from './ws-channel';
|
|
12
7
|
|
|
13
8
|
export interface IPathHandler {
|
|
14
9
|
dispose: (channel: WSChannel, connectionId: string) => void;
|
|
@@ -105,12 +100,21 @@ export class CommonChannelPathHandler {
|
|
|
105
100
|
|
|
106
101
|
export const commonChannelPathHandler = new CommonChannelPathHandler();
|
|
107
102
|
|
|
103
|
+
export interface ChannelHandlerOptions {
|
|
104
|
+
serializer?: ISerializer<ChannelMessage, any>;
|
|
105
|
+
}
|
|
106
|
+
|
|
108
107
|
export abstract class BaseCommonChannelHandler {
|
|
109
108
|
protected channelMap: Map<string, WSServerChannel> = new Map();
|
|
110
109
|
|
|
111
110
|
protected heartbeatTimer: NodeJS.Timeout | null = null;
|
|
112
111
|
|
|
113
|
-
|
|
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
|
+
}
|
|
114
118
|
|
|
115
119
|
abstract doHeartbeat(connection: any): void;
|
|
116
120
|
|
|
@@ -129,24 +133,20 @@ export abstract class BaseCommonChannelHandler {
|
|
|
129
133
|
let clientId: string;
|
|
130
134
|
this.heartbeat(connection);
|
|
131
135
|
|
|
136
|
+
const wrappedConnection = wrapSerializer(connection, this.serializer);
|
|
137
|
+
|
|
132
138
|
const getOrCreateChannel = (id: string, clientId: string) => {
|
|
133
139
|
let channel = this.channelMap.get(id);
|
|
134
140
|
if (!channel) {
|
|
135
|
-
channel = new WSServerChannel(
|
|
141
|
+
channel = new WSServerChannel(wrappedConnection, { id, clientId, logger: this.logger });
|
|
136
142
|
this.channelMap.set(id, channel);
|
|
137
143
|
}
|
|
138
144
|
return channel;
|
|
139
145
|
};
|
|
140
146
|
|
|
141
|
-
|
|
142
|
-
let msg: ChannelMessage;
|
|
147
|
+
wrappedConnection.onMessage((msg: ChannelMessage) => {
|
|
143
148
|
try {
|
|
144
|
-
msg = parse(data);
|
|
145
|
-
|
|
146
149
|
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,14 +163,12 @@ export abstract class BaseCommonChannelHandler {
|
|
|
163
163
|
if (channel) {
|
|
164
164
|
channel.dispatch(msg);
|
|
165
165
|
} else {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}),
|
|
173
|
-
);
|
|
166
|
+
wrappedConnection.send({
|
|
167
|
+
kind: 'error',
|
|
168
|
+
id,
|
|
169
|
+
code: ErrorMessageCode.ChannelNotFound,
|
|
170
|
+
message: `channel ${id} not found`,
|
|
171
|
+
});
|
|
174
172
|
|
|
175
173
|
this.logger.warn(`channel ${id} is not found`);
|
|
176
174
|
}
|
package/src/common/ws-channel.ts
CHANGED
|
@@ -1,60 +1,11 @@
|
|
|
1
|
-
import { Type } from '@furyjs/fury';
|
|
2
|
-
|
|
3
1
|
import { EventEmitter } from '@opensumi/events';
|
|
4
|
-
import {
|
|
5
|
-
DisposableCollection,
|
|
6
|
-
DisposableStore,
|
|
7
|
-
EventQueue,
|
|
8
|
-
StateTracer,
|
|
9
|
-
randomString,
|
|
10
|
-
} from '@opensumi/ide-core-common';
|
|
2
|
+
import { DisposableStore, EventQueue, StateTracer, randomString } from '@opensumi/ide-core-common';
|
|
11
3
|
|
|
4
|
+
import { ChannelMessage, ErrorMessageCode } from './channel/types';
|
|
12
5
|
import { IConnectionShape } from './connection/types';
|
|
13
|
-
import { oneOf } from './fury-extends/one-of';
|
|
14
6
|
import { ISumiConnectionOptions, SumiConnection } from './rpc/connection';
|
|
15
7
|
import { ILogger } from './types';
|
|
16
8
|
|
|
17
|
-
/**
|
|
18
|
-
* `ping` and `pong` are used to detect whether the connection is alive.
|
|
19
|
-
*/
|
|
20
|
-
export interface PingMessage {
|
|
21
|
-
kind: 'ping';
|
|
22
|
-
id: string;
|
|
23
|
-
clientId: string;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* when server receive a `ping` message, it should reply a `pong` message, vice versa.
|
|
28
|
-
*/
|
|
29
|
-
export interface PongMessage {
|
|
30
|
-
kind: 'pong';
|
|
31
|
-
id: string;
|
|
32
|
-
clientId: string;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* `data` message indicate that the channel has received some data.
|
|
37
|
-
* the `content` field is the data, it should be a string.
|
|
38
|
-
*/
|
|
39
|
-
export interface DataMessage {
|
|
40
|
-
kind: 'data';
|
|
41
|
-
id: string;
|
|
42
|
-
content: string;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export interface BinaryMessage {
|
|
46
|
-
kind: 'binary';
|
|
47
|
-
id: string;
|
|
48
|
-
binary: Uint8Array;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export interface CloseMessage {
|
|
52
|
-
kind: 'close';
|
|
53
|
-
id: string;
|
|
54
|
-
code: number;
|
|
55
|
-
reason: string;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
9
|
export interface IWSChannelCreateOptions {
|
|
59
10
|
/**
|
|
60
11
|
* every channel's unique id, it only used in client to server architecture.
|
|
@@ -80,37 +31,23 @@ export class WSChannel {
|
|
|
80
31
|
|
|
81
32
|
protected onBinaryQueue = this._disposables.add(new EventQueue<Uint8Array>());
|
|
82
33
|
|
|
83
|
-
protected sendQueue:
|
|
34
|
+
protected sendQueue: ChannelMessage[] = [];
|
|
84
35
|
protected _isServerReady = false;
|
|
85
36
|
protected _ensureServerReady: boolean | undefined;
|
|
86
37
|
|
|
87
38
|
public id: string;
|
|
88
39
|
|
|
89
40
|
public channelPath: string;
|
|
41
|
+
public clientId: string;
|
|
90
42
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
static forClient(connection: IConnectionShape<Uint8Array>, options: IWSChannelCreateOptions) {
|
|
94
|
-
const disposable = new DisposableCollection();
|
|
95
|
-
const channel = new WSChannel(connection, options);
|
|
96
|
-
|
|
97
|
-
disposable.push(
|
|
98
|
-
connection.onMessage((data) => {
|
|
99
|
-
channel.dispatch(parse(data));
|
|
100
|
-
}),
|
|
101
|
-
);
|
|
43
|
+
protected LOG_TAG = '[WSChannel]';
|
|
102
44
|
|
|
103
|
-
|
|
104
|
-
disposable.dispose();
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
return channel;
|
|
108
|
-
}
|
|
45
|
+
logger: ILogger = console;
|
|
109
46
|
|
|
110
|
-
constructor(public connection: IConnectionShape<
|
|
47
|
+
constructor(public connection: IConnectionShape<ChannelMessage>, options: IWSChannelCreateOptions) {
|
|
111
48
|
const { id, logger, ensureServerReady } = options;
|
|
112
49
|
this.id = id;
|
|
113
|
-
|
|
50
|
+
this.LOG_TAG = `[WSChannel id:${this.id}]`;
|
|
114
51
|
if (logger) {
|
|
115
52
|
this.logger = logger;
|
|
116
53
|
}
|
|
@@ -120,7 +57,7 @@ export class WSChannel {
|
|
|
120
57
|
this._disposables.add(this.emitter.on('binary', (data) => this.onBinaryQueue.push(data)));
|
|
121
58
|
}
|
|
122
59
|
|
|
123
|
-
protected inqueue(data:
|
|
60
|
+
protected inqueue(data: ChannelMessage) {
|
|
124
61
|
if (this._ensureServerReady && !this._isServerReady) {
|
|
125
62
|
if (!this.sendQueue) {
|
|
126
63
|
this.sendQueue = [];
|
|
@@ -182,6 +119,20 @@ export class WSChannel {
|
|
|
182
119
|
case 'binary':
|
|
183
120
|
this.emitter.emit('binary', msg.binary);
|
|
184
121
|
break;
|
|
122
|
+
case 'error':
|
|
123
|
+
this.logger.error(this.LOG_TAG, `receive error: id: ${msg.id}, code: ${msg.code}, error: ${msg.message}`);
|
|
124
|
+
switch (msg.code) {
|
|
125
|
+
case ErrorMessageCode.ChannelNotFound:
|
|
126
|
+
// 有 channelPath 说明该 channel 曾经被打开过
|
|
127
|
+
// 重新打开 channel
|
|
128
|
+
if (this.channelPath) {
|
|
129
|
+
// 暂停消息发送, 直到收到 server-ready
|
|
130
|
+
this.pause();
|
|
131
|
+
this.open(this.channelPath, this.clientId);
|
|
132
|
+
}
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
break;
|
|
185
136
|
}
|
|
186
137
|
}
|
|
187
138
|
|
|
@@ -192,6 +143,9 @@ export class WSChannel {
|
|
|
192
143
|
*/
|
|
193
144
|
open(path: string, clientId: string, connectionToken = randomString(16)) {
|
|
194
145
|
this.channelPath = path;
|
|
146
|
+
this.clientId = clientId;
|
|
147
|
+
|
|
148
|
+
this.LOG_TAG = `[WSChannel id=${this.id} path=${path}]`;
|
|
195
149
|
|
|
196
150
|
if (this.stateTracer.has(connectionToken)) {
|
|
197
151
|
this.logger.warn(
|
|
@@ -202,15 +156,13 @@ export class WSChannel {
|
|
|
202
156
|
|
|
203
157
|
this.stateTracer.record(connectionToken);
|
|
204
158
|
|
|
205
|
-
this.connection.send(
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
}),
|
|
213
|
-
);
|
|
159
|
+
this.connection.send({
|
|
160
|
+
kind: 'open',
|
|
161
|
+
id: this.id,
|
|
162
|
+
path,
|
|
163
|
+
clientId,
|
|
164
|
+
connectionToken,
|
|
165
|
+
});
|
|
214
166
|
|
|
215
167
|
if (this._ensureServerReady) {
|
|
216
168
|
this.ensureOpenSend(path, clientId, connectionToken);
|
|
@@ -237,23 +189,19 @@ export class WSChannel {
|
|
|
237
189
|
}
|
|
238
190
|
|
|
239
191
|
send(content: string) {
|
|
240
|
-
this.inqueue(
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
}),
|
|
246
|
-
);
|
|
192
|
+
this.inqueue({
|
|
193
|
+
kind: 'data',
|
|
194
|
+
id: this.id,
|
|
195
|
+
content,
|
|
196
|
+
});
|
|
247
197
|
}
|
|
248
198
|
|
|
249
199
|
sendBinary(data: Uint8Array) {
|
|
250
|
-
this.inqueue(
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
}),
|
|
256
|
-
);
|
|
200
|
+
this.inqueue({
|
|
201
|
+
kind: 'binary',
|
|
202
|
+
id: this.id,
|
|
203
|
+
binary: data,
|
|
204
|
+
});
|
|
257
205
|
}
|
|
258
206
|
onError() {}
|
|
259
207
|
close(code?: number, reason?: string) {
|
|
@@ -293,6 +241,13 @@ export class WSChannel {
|
|
|
293
241
|
this.sendQueue = [];
|
|
294
242
|
this._disposables.dispose();
|
|
295
243
|
}
|
|
244
|
+
|
|
245
|
+
ping() {
|
|
246
|
+
this.connection.send({
|
|
247
|
+
kind: 'ping',
|
|
248
|
+
id: this.id,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
296
251
|
}
|
|
297
252
|
|
|
298
253
|
interface IWSServerChannelCreateOptions extends IWSChannelCreateOptions {
|
|
@@ -306,18 +261,17 @@ export class WSServerChannel extends WSChannel {
|
|
|
306
261
|
messageQueue: ChannelMessage[] = [];
|
|
307
262
|
|
|
308
263
|
clientId: string;
|
|
309
|
-
constructor(public connection: IConnectionShape<
|
|
264
|
+
constructor(public connection: IConnectionShape<ChannelMessage>, options: IWSServerChannelCreateOptions) {
|
|
310
265
|
super(connection, options);
|
|
311
266
|
this.clientId = options.clientId;
|
|
312
267
|
}
|
|
268
|
+
|
|
313
269
|
serverReady(token: string) {
|
|
314
|
-
this.connection.send(
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
}),
|
|
320
|
-
);
|
|
270
|
+
this.connection.send({
|
|
271
|
+
kind: 'server-ready',
|
|
272
|
+
id: this.id,
|
|
273
|
+
token,
|
|
274
|
+
});
|
|
321
275
|
}
|
|
322
276
|
|
|
323
277
|
dispatch(msg: ChannelMessage) {
|
|
@@ -328,128 +282,12 @@ export class WSServerChannel extends WSChannel {
|
|
|
328
282
|
case 'binary':
|
|
329
283
|
this.emitter.emit('binary', msg.binary);
|
|
330
284
|
break;
|
|
285
|
+
case 'ping':
|
|
286
|
+
this.connection.send({
|
|
287
|
+
kind: 'pong',
|
|
288
|
+
id: this.id,
|
|
289
|
+
});
|
|
290
|
+
break;
|
|
331
291
|
}
|
|
332
292
|
}
|
|
333
293
|
}
|
|
334
|
-
|
|
335
|
-
export type ChannelMessage =
|
|
336
|
-
| PingMessage
|
|
337
|
-
| PongMessage
|
|
338
|
-
| OpenMessage
|
|
339
|
-
| ServerReadyMessage
|
|
340
|
-
| DataMessage
|
|
341
|
-
| BinaryMessage
|
|
342
|
-
| CloseMessage
|
|
343
|
-
| ErrorMessage;
|
|
344
|
-
|
|
345
|
-
export const PingProtocol = Type.object('ping', {
|
|
346
|
-
clientId: Type.string(),
|
|
347
|
-
id: Type.string(),
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
export const PongProtocol = Type.object('pong', {
|
|
351
|
-
clientId: Type.string(),
|
|
352
|
-
id: Type.string(),
|
|
353
|
-
});
|
|
354
|
-
|
|
355
|
-
/**
|
|
356
|
-
* `open` message is used to open a new channel.
|
|
357
|
-
* `path` is used to identify which handler should be used to handle the channel.
|
|
358
|
-
* `clientId` is used to identify the client.
|
|
359
|
-
*/
|
|
360
|
-
export interface OpenMessage {
|
|
361
|
-
kind: 'open';
|
|
362
|
-
id: string;
|
|
363
|
-
path: string;
|
|
364
|
-
clientId: string;
|
|
365
|
-
connectionToken: string;
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
export const OpenProtocol = Type.object('open', {
|
|
369
|
-
clientId: Type.string(),
|
|
370
|
-
id: Type.string(),
|
|
371
|
-
path: Type.string(),
|
|
372
|
-
connectionToken: Type.string(),
|
|
373
|
-
});
|
|
374
|
-
|
|
375
|
-
/**
|
|
376
|
-
* when server receive a `open` message, it should reply a `server-ready` message.
|
|
377
|
-
* this is indicate that the channel is ready to use.
|
|
378
|
-
*/
|
|
379
|
-
export interface ServerReadyMessage {
|
|
380
|
-
kind: 'server-ready';
|
|
381
|
-
id: string;
|
|
382
|
-
token: string;
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
export const ServerReadyProtocol = Type.object('server-ready', {
|
|
386
|
-
id: Type.string(),
|
|
387
|
-
token: Type.string(),
|
|
388
|
-
});
|
|
389
|
-
|
|
390
|
-
export enum ErrorMessageCode {
|
|
391
|
-
ChannelNotFound = 1,
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
export interface ErrorMessage {
|
|
395
|
-
kind: 'error';
|
|
396
|
-
id: string;
|
|
397
|
-
code: ErrorMessageCode;
|
|
398
|
-
message: string;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
export const ErrorProtocol = Type.object('error', {
|
|
402
|
-
id: Type.string(),
|
|
403
|
-
code: Type.uint16(),
|
|
404
|
-
message: Type.string(),
|
|
405
|
-
});
|
|
406
|
-
|
|
407
|
-
export const DataProtocol = Type.object('data', {
|
|
408
|
-
id: Type.string(),
|
|
409
|
-
content: Type.string(),
|
|
410
|
-
});
|
|
411
|
-
|
|
412
|
-
export const BinaryProtocol = Type.object('binary', {
|
|
413
|
-
id: Type.string(),
|
|
414
|
-
binary: Type.binary(),
|
|
415
|
-
});
|
|
416
|
-
|
|
417
|
-
export const CloseProtocol = Type.object('close', {
|
|
418
|
-
id: Type.string(),
|
|
419
|
-
code: Type.uint32(),
|
|
420
|
-
reason: Type.string(),
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
const serializer = oneOf([
|
|
424
|
-
PingProtocol,
|
|
425
|
-
PongProtocol,
|
|
426
|
-
OpenProtocol,
|
|
427
|
-
ServerReadyProtocol,
|
|
428
|
-
DataProtocol,
|
|
429
|
-
BinaryProtocol,
|
|
430
|
-
CloseProtocol,
|
|
431
|
-
ErrorProtocol,
|
|
432
|
-
]);
|
|
433
|
-
|
|
434
|
-
export function stringify(obj: ChannelMessage): Uint8Array {
|
|
435
|
-
return serializer.serialize(obj);
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
export function parse(input: Uint8Array): ChannelMessage {
|
|
439
|
-
return serializer.deserialize(input) as any;
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
const _pingMessage: PingMessage = {
|
|
443
|
-
kind: 'ping',
|
|
444
|
-
id: '',
|
|
445
|
-
clientId: '',
|
|
446
|
-
};
|
|
447
|
-
|
|
448
|
-
const _pongMessage: PongMessage = {
|
|
449
|
-
kind: 'pong',
|
|
450
|
-
id: '',
|
|
451
|
-
clientId: '',
|
|
452
|
-
};
|
|
453
|
-
|
|
454
|
-
export const pingMessage = stringify(_pingMessage);
|
|
455
|
-
export const pongMessage = stringify(_pongMessage);
|