@@ -5,8 +5,8 @@ import { Emitter } from "@coder/events";
5
5
import { logger , field } from "@coder/logger" ;
6
6
import { ReadWriteConnection , InitData , SharedProcessData } from "../common/connection" ;
7
7
import { Module , ServerProxy } from "../common/proxy" ;
8
- import { stringify , parse , moduleToProto , protoToModule , protoToOperatingSystem } from "../common/util" ;
9
- import { Ping , ServerMessage , ClientMessage , MethodMessage , NamedProxyMessage , NumberedProxyMessage , SuccessMessage , FailMessage , EventMessage , CallbackMessage } from "../proto" ;
8
+ import { argumentToProto , protoToArgument , moduleToProto , protoToModule , protoToOperatingSystem } from "../common/util" ;
9
+ import { Argument , Ping , ServerMessage , ClientMessage , Method , Event , Callback } from "../proto" ;
10
10
import { FsModule , ChildProcessModule , NetModule , NodePtyModule , SpdlogModule , TrashModule } from "./modules" ;
11
11
12
12
// tslint:disable no-any
@@ -24,8 +24,8 @@ export class Client {
24
24
private messageId = 0 ;
25
25
private callbackId = 0 ;
26
26
private readonly proxies = new Map < number | Module , ProxyData > ( ) ;
27
- private readonly successEmitter = new Emitter < SuccessMessage > ( ) ;
28
- private readonly failEmitter = new Emitter < FailMessage > ( ) ;
27
+ private readonly successEmitter = new Emitter < Method . Success > ( ) ;
28
+ private readonly failEmitter = new Emitter < Method . Fail > ( ) ;
29
29
private readonly eventEmitter = new Emitter < { event : string ; args : any [ ] ; } > ( ) ;
30
30
31
31
private _initData : InitData | undefined ;
@@ -129,9 +129,9 @@ export class Client {
129
129
field ( "event listeners" , this . eventEmitter . counts ) ,
130
130
] ) ;
131
131
132
- const message = new FailMessage ( ) ;
132
+ const message = new Method . Fail ( ) ;
133
133
const error = new Error ( "disconnected" ) ;
134
- message . setResponse ( stringify ( error ) ) ;
134
+ message . setResponse ( argumentToProto ( error ) ) ;
135
135
this . failEmitter . emit ( message ) ;
136
136
137
137
this . eventEmitter . emit ( { event : "disconnected" , args : [ error ] } ) ;
@@ -182,20 +182,21 @@ export class Client {
182
182
case "kill" :
183
183
return Promise . resolve ( ) ;
184
184
}
185
+
185
186
return Promise . reject (
186
187
new Error ( `Unable to call "${ method } " on proxy ${ proxyId } : disconnected` ) ,
187
188
) ;
188
189
}
189
190
190
- const message = new MethodMessage ( ) ;
191
+ const message = new Method ( ) ;
191
192
const id = this . messageId ++ ;
192
- let proxyMessage : NamedProxyMessage | NumberedProxyMessage ;
193
+ let proxyMessage : Method . Named | Method . Numbered ;
193
194
if ( typeof proxyId === "string" ) {
194
- proxyMessage = new NamedProxyMessage ( ) ;
195
+ proxyMessage = new Method . Named ( ) ;
195
196
proxyMessage . setModule ( moduleToProto ( proxyId ) ) ;
196
197
message . setNamedProxy ( proxyMessage ) ;
197
198
} else {
198
- proxyMessage = new NumberedProxyMessage ( ) ;
199
+ proxyMessage = new Method . Numbered ( ) ;
199
200
proxyMessage . setProxyId ( proxyId ) ;
200
201
message . setNumberedProxy ( proxyMessage ) ;
201
202
}
@@ -215,16 +216,14 @@ export class Client {
215
216
return callbackId ;
216
217
} ;
217
218
218
- const stringifiedArgs = args . map ( ( a ) => stringify ( a , storeCallback ) ) ;
219
219
logger . trace ( ( ) => [
220
220
"sending" ,
221
221
field ( "id" , id ) ,
222
222
field ( "proxyId" , proxyId ) ,
223
223
field ( "method" , method ) ,
224
- field ( "args" , stringifiedArgs ) ,
225
224
] ) ;
226
225
227
- proxyMessage . setArgsList ( stringifiedArgs ) ;
226
+ proxyMessage . setArgsList ( args . map ( ( a ) => argumentToProto ( a , storeCallback ) ) ) ;
228
227
229
228
const clientMessage = new ClientMessage ( ) ;
230
229
clientMessage . setMethod ( message ) ;
@@ -246,12 +245,12 @@ export class Client {
246
245
247
246
const d1 = this . successEmitter . event ( id , ( message ) => {
248
247
dispose ( ) ;
249
- resolve ( this . parse ( message . getResponse ( ) , promise ) ) ;
248
+ resolve ( this . protoToArgument ( message . getResponse ( ) , promise ) ) ;
250
249
} ) ;
251
250
252
251
const d2 = this . failEmitter . event ( id , ( message ) => {
253
252
dispose ( ) ;
254
- reject ( parse ( message . getResponse ( ) ) ) ;
253
+ reject ( protoToArgument ( message . getResponse ( ) ) ) ;
255
254
} ) ;
256
255
} ) ;
257
256
@@ -262,42 +261,53 @@ export class Client {
262
261
* Handle all messages from the server.
263
262
*/
264
263
private async handleMessage ( message : ServerMessage ) : Promise < void > {
265
- if ( message . hasInit ( ) ) {
266
- const init = message . getInit ( ) ! ;
267
- this . _initData = {
268
- dataDirectory : init . getDataDirectory ( ) ,
269
- homeDirectory : init . getHomeDirectory ( ) ,
270
- tmpDirectory : init . getTmpDirectory ( ) ,
271
- workingDirectory : init . getWorkingDirectory ( ) ,
272
- os : protoToOperatingSystem ( init . getOperatingSystem ( ) ) ,
273
- shell : init . getShell ( ) ,
274
- builtInExtensionsDirectory : init . getBuiltinExtensionsDir ( ) ,
275
- } ;
276
- this . initDataEmitter . emit ( this . _initData ) ;
277
- } else if ( message . hasSuccess ( ) ) {
278
- this . emitSuccess ( message . getSuccess ( ) ! ) ;
279
- } else if ( message . hasFail ( ) ) {
280
- this . emitFail ( message . getFail ( ) ! ) ;
281
- } else if ( message . hasEvent ( ) ) {
282
- await this . emitEvent ( message . getEvent ( ) ! ) ;
283
- } else if ( message . hasCallback ( ) ) {
284
- await this . runCallback ( message . getCallback ( ) ! ) ;
285
- } else if ( message . hasSharedProcessActive ( ) ) {
286
- const sharedProcessActiveMessage = message . getSharedProcessActive ( ) ! ;
287
- this . sharedProcessActiveEmitter . emit ( {
288
- socketPath : sharedProcessActiveMessage . getSocketPath ( ) ,
289
- logPath : sharedProcessActiveMessage . getLogPath ( ) ,
290
- } ) ;
291
- } else if ( message . hasPong ( ) ) {
292
- // Nothing to do since pings are on a timer rather than waiting for the
293
- // next pong in case a message from either the client or server is dropped
294
- // which would break the ping cycle.
295
- } else {
296
- throw new Error ( "unknown message type" ) ;
264
+ switch ( message . getMsgCase ( ) ) {
265
+ case ServerMessage . MsgCase . INIT :
266
+ const init = message . getInit ( ) ! ;
267
+ this . _initData = {
268
+ dataDirectory : init . getDataDirectory ( ) ,
269
+ homeDirectory : init . getHomeDirectory ( ) ,
270
+ tmpDirectory : init . getTmpDirectory ( ) ,
271
+ workingDirectory : init . getWorkingDirectory ( ) ,
272
+ os : protoToOperatingSystem ( init . getOperatingSystem ( ) ) ,
273
+ shell : init . getShell ( ) ,
274
+ builtInExtensionsDirectory : init . getBuiltinExtensionsDir ( ) ,
275
+ } ;
276
+ this . initDataEmitter . emit ( this . _initData ) ;
277
+ break ;
278
+ case ServerMessage . MsgCase . SUCCESS :
279
+ this . emitSuccess ( message . getSuccess ( ) ! ) ;
280
+ break ;
281
+ case ServerMessage . MsgCase . FAIL :
282
+ this . emitFail ( message . getFail ( ) ! ) ;
283
+ break ;
284
+ case ServerMessage . MsgCase . EVENT :
285
+ await this . emitEvent ( message . getEvent ( ) ! ) ;
286
+ break ;
287
+ case ServerMessage . MsgCase . CALLBACK :
288
+ await this . runCallback ( message . getCallback ( ) ! ) ;
289
+ break ;
290
+ case ServerMessage . MsgCase . SHARED_PROCESS_ACTIVE :
291
+ const sharedProcessActiveMessage = message . getSharedProcessActive ( ) ! ;
292
+ this . sharedProcessActiveEmitter . emit ( {
293
+ socketPath : sharedProcessActiveMessage . getSocketPath ( ) ,
294
+ logPath : sharedProcessActiveMessage . getLogPath ( ) ,
295
+ } ) ;
296
+ break ;
297
+ case ServerMessage . MsgCase . PONG :
298
+ // Nothing to do since pings are on a timer rather than waiting for the
299
+ // next pong in case a message from either the client or server is dropped
300
+ // which would break the ping cycle.
301
+ break ;
302
+ default :
303
+ throw new Error ( "unknown message type" ) ;
297
304
}
298
305
}
299
306
300
- private emitSuccess ( message : SuccessMessage ) : void {
307
+ /**
308
+ * Convert message to a success event.
309
+ */
310
+ private emitSuccess ( message : Method . Success ) : void {
301
311
logger . trace ( ( ) => [
302
312
"received resolve" ,
303
313
field ( "id" , message . getId ( ) ) ,
@@ -306,7 +316,10 @@ export class Client {
306
316
this . successEmitter . emit ( message . getId ( ) , message ) ;
307
317
}
308
318
309
- private emitFail ( message : FailMessage ) : void {
319
+ /**
320
+ * Convert message to a fail event.
321
+ */
322
+ private emitFail ( message : Method . Fail ) : void {
310
323
logger . trace ( ( ) => [
311
324
"received reject" ,
312
325
field ( "id" , message . getId ( ) ) ,
@@ -322,7 +335,7 @@ export class Client {
322
335
* request before it emits. Instead, emit all events from the server so all
323
336
* events are always caught on the client.
324
337
*/
325
- private async emitEvent ( message : EventMessage ) : Promise < void > {
338
+ private async emitEvent ( message : Event ) : Promise < void > {
326
339
const eventMessage = message . getNamedEvent ( ) ! || message . getNumberedEvent ( ) ! ;
327
340
const proxyId = message . getNamedEvent ( )
328
341
? protoToModule ( message . getNamedEvent ( ) ! . getModule ( ) )
@@ -333,10 +346,9 @@ export class Client {
333
346
"received event" ,
334
347
field ( "proxyId" , proxyId ) ,
335
348
field ( "event" , event ) ,
336
- field ( "args" , eventMessage . getArgsList ( ) ) ,
337
349
] ) ;
338
350
339
- const args = eventMessage . getArgsList ( ) . map ( ( a ) => this . parse ( a ) ) ;
351
+ const args = eventMessage . getArgsList ( ) . map ( ( a ) => this . protoToArgument ( a ) ) ;
340
352
this . eventEmitter . emit ( proxyId , { event, args } ) ;
341
353
}
342
354
@@ -348,7 +360,7 @@ export class Client {
348
360
* also only be used when passed together with the method. If they are sent
349
361
* afterward, they may never be called due to timing issues.
350
362
*/
351
- private async runCallback ( message : CallbackMessage ) : Promise < void > {
363
+ private async runCallback ( message : Callback ) : Promise < void > {
352
364
const callbackMessage = message . getNamedCallback ( ) ! || message . getNumberedCallback ( ) ! ;
353
365
const proxyId = message . getNamedCallback ( )
354
366
? protoToModule ( message . getNamedCallback ( ) ! . getModule ( ) )
@@ -359,16 +371,15 @@ export class Client {
359
371
"running callback" ,
360
372
field ( "proxyId" , proxyId ) ,
361
373
field ( "callbackId" , callbackId ) ,
362
- field ( "args" , callbackMessage . getArgsList ( ) ) ,
363
374
] ) ;
364
- const args = callbackMessage . getArgsList ( ) . map ( ( a ) => this . parse ( a ) ) ;
375
+ const args = callbackMessage . getArgsList ( ) . map ( ( a ) => this . protoToArgument ( a ) ) ;
365
376
this . getProxy ( proxyId ) . callbacks . get ( callbackId ) ! ( ...args ) ;
366
377
}
367
378
368
379
/**
369
380
* Start the ping loop. Does nothing if already pinging.
370
381
*/
371
- private startPinging = ( ) : void => {
382
+ private readonly startPinging = ( ) : void => {
372
383
if ( typeof this . pingTimeout !== "undefined" ) {
373
384
return ;
374
385
}
@@ -505,10 +516,16 @@ export class Client {
505
516
await this . getProxy ( proxyId ) . promise ;
506
517
}
507
518
508
- private parse ( value ?: string , promise ?: Promise < any > ) : any {
509
- return parse ( value , undefined , ( id ) => this . createProxy ( id , promise ) ) ;
519
+ /**
520
+ * Same as protoToArgument except provides createProxy.
521
+ */
522
+ private protoToArgument ( value ?: Argument , promise ?: Promise < any > ) : any {
523
+ return protoToArgument ( value , undefined , ( id ) => this . createProxy ( id , promise ) ) ;
510
524
}
511
525
526
+ /**
527
+ * Get a proxy. Error if it doesn't exist.
528
+ */
512
529
private getProxy ( proxyId : number | Module ) : ProxyData {
513
530
if ( ! this . proxies . has ( proxyId ) ) {
514
531
throw new Error ( `proxy ${ proxyId } disposed too early` ) ;
0 commit comments