@agoric/network 0.1.1-dev-501c093.0 → 0.1.1-dev-db972d4.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/src/network.js CHANGED
@@ -4,6 +4,7 @@ import { E } from '@endo/far';
4
4
  import { M } from '@endo/patterns';
5
5
  import { Fail } from '@agoric/assert';
6
6
  import { toBytes } from './bytes.js';
7
+ import { Shape } from './shapes.js';
7
8
 
8
9
  import '@agoric/store/exported.js';
9
10
  /// <reference path="./types.js" />
@@ -14,202 +15,13 @@ import '@agoric/store/exported.js';
14
15
  */
15
16
  export const ENDPOINT_SEPARATOR = '/';
16
17
 
17
- const Shape1 = /** @type {const} */ ({
18
- /**
19
- * Data is string | Buffer | ArrayBuffer
20
- * but only string is passable
21
- */
22
- Data: M.string(),
23
- Bytes: M.string(),
24
- Endpoint: M.string(),
25
- Vow: M.tagged(
26
- 'Vow',
27
- harden({
28
- vowV0: M.remotable('VowV0'),
29
- }),
30
- ),
31
- ConnectionHandler: M.remotable('ConnectionHandler'),
32
- Connection: M.remotable('Connection'),
33
- InboundAttempt: M.remotable('InboundAttempt'),
34
- Listener: M.remotable('Listener'),
35
- ListenHandler: M.remotable('ListenHandler'),
36
- Port: M.remotable('Port'),
37
- ProtocolHandler: M.remotable('ProtocolHandler'),
38
- ProtocolImpl: M.remotable('ProtocolImpl'),
39
- });
40
-
41
- const Shape2 = /** @type {const} */ ({
42
- ...Shape1,
43
- Vow$: shape => M.or(shape, Shape1.Vow),
44
- AttemptDescription: M.splitRecord(
45
- { handler: Shape1.ConnectionHandler },
46
- { remoteAddress: Shape1.Endpoint, localAddress: Shape1.Endpoint },
47
- ),
48
- Opts: M.recordOf(M.string(), M.any()),
49
- });
50
-
51
- export const Shape = /** @type {const} */ harden({
52
- ...Shape2,
53
- ConnectionI: {
54
- connection: M.interface('Connection', {
55
- send: M.callWhen(Shape2.Data)
56
- .optional(Shape2.Opts)
57
- .returns(Shape2.Vow$(Shape2.Bytes)),
58
- close: M.callWhen().returns(Shape2.Vow$(M.undefined())),
59
- getLocalAddress: M.call().returns(Shape2.Endpoint),
60
- getRemoteAddress: M.call().returns(Shape2.Endpoint),
61
- }),
62
- openConnectionAckWatcher: M.interface('OpenConnectionAckWatcher', {
63
- onFulfilled: M.call(M.any()).rest(M.any()).returns(M.any()),
64
- }),
65
- rethrowUnlessMissingWatcher: M.interface('RethrowUnlessMissingWatcher', {
66
- onRejected: M.call(M.any()).rest(M.any()).returns(M.any()),
67
- }),
68
- sinkWatcher: M.interface('SinkWatcher', {
69
- onFulfilled: M.call(M.any()).rest(M.any()).returns(),
70
- }),
71
- },
72
- InboundAttemptI: {
73
- inboundAttempt: M.interface('InboundAttempt', {
74
- accept: M.callWhen(Shape2.AttemptDescription).returns(
75
- Shape2.Vow$(Shape2.Connection),
76
- ),
77
- getLocalAddress: M.call().returns(Shape2.Endpoint),
78
- getRemoteAddress: M.call().returns(Shape2.Endpoint),
79
- close: M.callWhen().returns(Shape2.Vow$(M.undefined())),
80
- }),
81
- inboundAttemptAcceptWatcher: M.interface('InboundAttemptAcceptWatcher', {
82
- onFulfilled: M.call(M.any()).rest(M.any()).returns(M.any()),
83
- }),
84
- rethrowUnlessMissingWatcher: M.interface('RethrowUnlessMissingWatcher', {
85
- onRejected: M.call(M.any()).rest(M.any()).returns(M.any()),
86
- }),
87
- sinkWatcher: M.interface('SinkWatcher', {
88
- onFulfilled: M.call(M.any()).rest(M.any()).returns(),
89
- }),
90
- },
91
- PortI: {
92
- port: M.interface('Port', {
93
- getLocalAddress: M.call().returns(Shape2.Endpoint),
94
- addListener: M.callWhen(Shape2.Listener).returns(
95
- Shape2.Vow$(M.undefined()),
96
- ),
97
- connect: M.callWhen(Shape2.Endpoint)
98
- .optional(Shape2.ConnectionHandler)
99
- .returns(Shape2.Vow$(Shape2.Connection)),
100
- removeListener: M.callWhen(Shape2.Listener).returns(
101
- Shape2.Vow$(M.undefined()),
102
- ),
103
- revoke: M.callWhen().returns(Shape2.Vow$(M.undefined())),
104
- }),
105
- portAddListenerWatcher: M.interface('PortAddListenerWatcher', {
106
- onFulfilled: M.call(M.any()).rest(M.any()).returns(M.any()),
107
- }),
108
- portRemoveListenerWatcher: M.interface('PortRemoveListenerWatcher', {
109
- onFulfilled: M.call(M.any()).rest(M.any()).returns(M.any()),
110
- }),
111
- portConnectWatcher: M.interface('PortConnectWatcher', {
112
- onFulfilled: M.call(M.any()).rest(M.any()).returns(M.any()),
113
- }),
114
- portRevokeWatcher: M.interface('PortRevokeWatcher', {
115
- onFulfilled: M.call(M.any()).rest(M.any()).returns(M.any()),
116
- }),
117
- portRevokeCleanupWatcher: M.interface('PortRevokeCleanupWatcher', {
118
- onFulfilled: M.call(M.any()).rest(M.any()).returns(M.any()),
119
- }),
120
- rethrowUnlessMissingWatcher: M.interface('RethrowUnlessMissingWatcher', {
121
- onRejected: M.call(M.any()).rest(M.any()).returns(M.any()),
122
- }),
123
- sinkWatcher: M.interface('SinkWatcher', {
124
- onFulfilled: M.call(M.any()).rest(M.any()).returns(),
125
- onRejected: M.call(M.any()).rest(M.any()).returns(M.any()),
126
- }),
127
- },
128
- ProtocolHandlerI: {
129
- protocolHandler: M.interface('ProtocolHandler', {
130
- onCreate: M.callWhen(M.remotable(), Shape2.ProtocolHandler).returns(
131
- Shape2.Vow$(M.undefined()),
132
- ),
133
- generatePortID: M.callWhen(
134
- Shape2.Endpoint,
135
- Shape2.ProtocolHandler,
136
- ).returns(Shape2.Vow$(M.string())),
137
- onBind: M.callWhen(
138
- Shape2.Port,
139
- Shape2.Endpoint,
140
- Shape2.ProtocolHandler,
141
- ).returns(Shape2.Vow$(M.undefined())),
142
- onListen: M.callWhen(
143
- Shape2.Port,
144
- Shape2.Endpoint,
145
- Shape2.ListenHandler,
146
- Shape2.ProtocolHandler,
147
- ).returns(Shape2.Vow$(M.undefined())),
148
- onListenRemove: M.callWhen(
149
- Shape2.Port,
150
- Shape2.Endpoint,
151
- Shape2.ListenHandler,
152
- Shape2.ProtocolHandler,
153
- ).returns(Shape2.Vow$(M.undefined())),
154
- onInstantiate: M.callWhen(
155
- Shape2.Port,
156
- Shape2.Endpoint,
157
- Shape2.Endpoint,
158
- Shape2.ProtocolHandler,
159
- ).returns(Shape2.Vow$(Shape2.Endpoint)),
160
- onConnect: M.callWhen(
161
- Shape2.Port,
162
- Shape2.Endpoint,
163
- Shape2.Endpoint,
164
- Shape2.ConnectionHandler,
165
- Shape2.ProtocolHandler,
166
- ).returns(Shape2.Vow$(Shape2.AttemptDescription)),
167
- onRevoke: M.callWhen(
168
- Shape2.Port,
169
- Shape2.Endpoint,
170
- Shape2.ProtocolHandler,
171
- ).returns(Shape2.Vow$(M.undefined())),
172
- }),
173
- protocolHandlerAcceptWatcher: M.interface('ProtocolHandlerAcceptWatcher', {
174
- onFulfilled: M.call(M.any()).rest(M.any()).returns(),
175
- }),
176
- protocolHandlerInstantiateWatcher: M.interface(
177
- 'ProtocolHandlerInstantiateWatcher',
178
- {
179
- onFulfilled: M.call(M.any()).rest(M.any()).returns(),
180
- },
181
- ),
182
- protocolHandlerConnectWatcher: M.interface(
183
- 'ProtocolHandlerConnectWatcher',
184
- {
185
- onFulfilled: M.call(M.any()).rest(M.any()).returns(),
186
- },
187
- ),
188
- rethrowUnlessMissingWatcher: M.interface('RethrowUnlessMissingWatcher', {
189
- onRejected: M.call(M.any()).rest(M.any()).returns(M.any()),
190
- }),
191
- },
192
-
193
- ProtocolImplI: M.interface('ProtocolImpl', {
194
- bind: M.callWhen(Shape2.Endpoint).returns(Shape2.Vow$(Shape2.Port)),
195
- inbound: M.callWhen(Shape2.Endpoint, Shape2.Endpoint).returns(
196
- Shape2.Vow$(Shape2.InboundAttempt),
197
- ),
198
- outbound: M.callWhen(
199
- Shape2.Port,
200
- Shape2.Endpoint,
201
- Shape2.ConnectionHandler,
202
- ).returns(Shape2.Vow$(Shape2.Connection)),
203
- }),
204
- });
205
-
206
18
  /** @param {unknown} err */
207
19
  export const rethrowUnlessMissing = err => {
208
20
  // Ugly hack rather than being able to determine if the function
209
21
  // exists.
210
22
  if (
211
23
  !(err instanceof TypeError) ||
212
- !err.message.match(/target has no method|is not a function$/)
24
+ !String(err.message).match(/target has no method|is not a function$/)
213
25
  ) {
214
26
  throw err;
215
27
  }
@@ -237,7 +49,7 @@ export function getPrefixes(addr) {
237
49
  /**
238
50
  * @typedef {object} ConnectionOpts
239
51
  * @property {Endpoint[]} addrs
240
- * @property {ConnectionHandler[]} handlers
52
+ * @property {import('@agoric/vow').Remote<Required<ConnectionHandler>>[]} handlers
241
53
  * @property {MapStore<number, Connection>} conns
242
54
  * @property {WeakSetStore<Closable>} current
243
55
  * @property {0|1} l
@@ -254,9 +66,6 @@ const prepareHalfConnection = (zone, { watch }) => {
254
66
  Shape.ConnectionI,
255
67
  /** @param {ConnectionOpts} opts */
256
68
  ({ addrs, handlers, conns, current, l, r }) => {
257
- /** @type {string | undefined} */
258
- let closed;
259
-
260
69
  return {
261
70
  addrs,
262
71
  handlers,
@@ -264,7 +73,8 @@ const prepareHalfConnection = (zone, { watch }) => {
264
73
  current,
265
74
  l,
266
75
  r,
267
- closed,
76
+ /** @type {string | undefined} */
77
+ closed: undefined,
268
78
  };
269
79
  },
270
80
  {
@@ -277,11 +87,11 @@ const prepareHalfConnection = (zone, { watch }) => {
277
87
  const { addrs, r } = this.state;
278
88
  return addrs[r];
279
89
  },
280
- /** @param {Data} packetBytes */
90
+ /** @param {Bytes} packetBytes */
281
91
  async send(packetBytes) {
282
92
  const { closed, handlers, r, conns } = this.state;
283
93
  if (closed) {
284
- throw closed;
94
+ throw Error(closed);
285
95
  }
286
96
 
287
97
  const innerVow = watch(
@@ -348,12 +158,12 @@ const prepareHalfConnection = (zone, { watch }) => {
348
158
 
349
159
  /**
350
160
  * @param {import('@agoric/zone').Zone} zone
351
- * @param {ConnectionHandler} handler0
161
+ * @param {import('@agoric/vow').Remote<Required<ConnectionHandler>>} handler0
352
162
  * @param {Endpoint} addr0
353
- * @param {ConnectionHandler} handler1
163
+ * @param {import('@agoric/vow').Remote<Required<ConnectionHandler>>} handler1
354
164
  * @param {Endpoint} addr1
355
165
  * @param {(opts: ConnectionOpts) => Connection} makeConnection
356
- * @param {WeakSetStore<Closable>} current
166
+ * @param {WeakSetStore<Closable>} [current]
357
167
  */
358
168
  export const crossoverConnection = (
359
169
  zone,
@@ -369,7 +179,7 @@ export const crossoverConnection = (
369
179
  /** @type {MapStore<number, Connection>} */
370
180
  const conns = detached.mapStore('addrToConnections');
371
181
 
372
- /** @type {ConnectionHandler[]} */
182
+ /** @type {import('@agoric/vow').Remote<Required<ConnectionHandler>>[]} */
373
183
  const handlers = harden([handler0, handler1]);
374
184
  /** @type {Endpoint[]} */
375
185
  const addrs = harden([addr0, addr1]);
@@ -415,9 +225,9 @@ const prepareInboundAttempt = (zone, makeConnection, { watch }) => {
415
225
  * @param {object} opts
416
226
  * @param {string} opts.localAddr
417
227
  * @param {string} opts.remoteAddr
418
- * @param { MapStore<Port, SetStore<Closable>> } opts.currentConnections
228
+ * @param {MapStore<Port, SetStore<Closable>>} opts.currentConnections
419
229
  * @param {string} opts.listenPrefix
420
- * @param {MapStore<Endpoint, [Port, ListenHandler]>} opts.listening
230
+ * @param {MapStore<Endpoint, [Port, import('@agoric/vow').Remote<Required<ListenHandler>>]>} opts.listening
421
231
  */
422
232
  ({
423
233
  localAddr,
@@ -472,7 +282,7 @@ const prepareInboundAttempt = (zone, makeConnection, { watch }) => {
472
282
  * @param {object} opts
473
283
  * @param {string} [opts.localAddress]
474
284
  * @param {string} [opts.remoteAddress]
475
- * @param {ConnectionHandler} opts.handler
285
+ * @param {import('@agoric/vow').Remote<ConnectionHandler>} opts.handler
476
286
  */
477
287
  async accept({ localAddress, remoteAddress, handler: rchandler }) {
478
288
  const { consummated, localAddr, remoteAddr } = this.state;
@@ -514,9 +324,13 @@ const prepareInboundAttempt = (zone, makeConnection, { watch }) => {
514
324
 
515
325
  return crossoverConnection(
516
326
  zone,
517
- lchandler,
327
+ /** @type {import('@agoric/vow').Remote<Required<ConnectionHandler>>} */ (
328
+ lchandler
329
+ ),
518
330
  localAddress,
519
- rchandler,
331
+ /** @type {import('@agoric/vow').Remote<Required<ConnectionHandler>>} */ (
332
+ rchandler
333
+ ),
520
334
  remoteAddress,
521
335
  makeConnection,
522
336
  current,
@@ -573,217 +387,222 @@ const preparePort = (zone, powers) => {
573
387
 
574
388
  const { watch, allVows } = powers;
575
389
 
576
- const makePortKit = zone.exoClassKit(
577
- 'Port',
578
- Shape.PortI,
579
- /**
580
- * @param {object} opts
581
- * @param {Endpoint} opts.localAddr
582
- * @param {MapStore<Endpoint, [Port, ListenHandler]>} opts.listening
583
- * @param {SetStore<Connection>} opts.openConnections
584
- * @param {MapStore<Port, SetStore<Closable>>} opts.currentConnections
585
- * @param {MapStore<string, Port>} opts.boundPorts
586
- * @param {ProtocolHandler} opts.protocolHandler
587
- * @param {ProtocolImpl} opts.protocolImpl
588
- */
589
- ({
590
- localAddr,
390
+ /**
391
+ * @param {object} opts
392
+ * @param {Endpoint} opts.localAddr
393
+ * @param {MapStore<Endpoint, [Port, import('@agoric/vow').Remote<Required<ListenHandler>>]>} opts.listening
394
+ * @param {SetStore<import('@agoric/vow').Remote<Connection>>} opts.openConnections
395
+ * @param {MapStore<Port, SetStore<Closable>>} opts.currentConnections
396
+ * @param {MapStore<string, Port>} opts.boundPorts
397
+ * @param {import('@agoric/vow').Remote<ProtocolHandler>} opts.protocolHandler
398
+ * @param {Remote<ProtocolImpl>} opts.protocolImpl
399
+ */
400
+ const initPort = ({
401
+ localAddr,
402
+ listening,
403
+ openConnections,
404
+ currentConnections,
405
+ boundPorts,
406
+ protocolHandler,
407
+ protocolImpl,
408
+ }) => {
409
+ return {
591
410
  listening,
592
411
  openConnections,
593
412
  currentConnections,
594
413
  boundPorts,
414
+ localAddr,
595
415
  protocolHandler,
596
416
  protocolImpl,
597
- }) => {
598
- return {
599
- listening,
600
- openConnections,
601
- currentConnections,
602
- boundPorts,
603
- localAddr,
604
- protocolHandler,
605
- protocolImpl,
606
- /** @type {RevokeState | undefined} */
607
- revoked: undefined,
608
- };
609
- },
610
- {
611
- port: {
612
- getLocalAddress() {
613
- // Works even after revoke().
614
- return this.state.localAddr;
615
- },
616
- /** @param {ListenHandler} listenHandler */
617
- async addListener(listenHandler) {
618
- const { revoked, listening, localAddr, protocolHandler } = this.state;
619
-
620
- !revoked || Fail`Port ${this.state.localAddr} is revoked`;
621
- listenHandler || Fail`listenHandler is not defined`;
622
-
623
- if (listening.has(localAddr)) {
624
- // Last one wins.
625
- const [lport, lhandler] = listening.get(localAddr);
626
- if (lhandler === listenHandler) {
627
- return;
628
- }
629
- listening.set(localAddr, [this.facets.port, listenHandler]);
630
- E(lhandler).onRemove(lport, lhandler).catch(rethrowUnlessMissing);
631
- } else {
632
- listening.init(
633
- localAddr,
634
- harden([this.facets.port, listenHandler]),
635
- );
636
- }
637
-
638
- // ASSUME: that the listener defines onAccept.
417
+ /** @type {RevokeState | undefined} */
418
+ revoked: undefined,
419
+ };
420
+ };
639
421
 
640
- const innerVow = watch(
641
- E(protocolHandler).onListen(
422
+ const makePortKit = zone.exoClassKit('Port', Shape.PortI, initPort, {
423
+ port: {
424
+ getLocalAddress() {
425
+ // Works even after revoke().
426
+ return this.state.localAddr;
427
+ },
428
+ /** @param {import('@agoric/vow').Remote<ListenHandler>} listenHandler */
429
+ async addListener(listenHandler) {
430
+ const { revoked, listening, localAddr, protocolHandler } = this.state;
431
+
432
+ !revoked || Fail`Port ${this.state.localAddr} is revoked`;
433
+ listenHandler || Fail`listenHandler is not defined`;
434
+
435
+ if (listening.has(localAddr)) {
436
+ // Last one wins.
437
+ const [lport, lhandler] = listening.get(localAddr);
438
+ if (lhandler === listenHandler) {
439
+ return;
440
+ }
441
+ listening.set(localAddr, [
442
+ this.facets.port,
443
+ /** @type {Remote<Required<ListenHandler>>} */ (listenHandler),
444
+ ]);
445
+ E(lhandler).onRemove(lport, lhandler).catch(rethrowUnlessMissing);
446
+ } else {
447
+ listening.init(
448
+ localAddr,
449
+ harden([
642
450
  this.facets.port,
643
- localAddr,
644
- listenHandler,
645
- protocolHandler,
646
- ),
647
- this.facets.portAddListenerWatcher,
648
- { listenHandler },
451
+ /** @type {Remote<Required<ListenHandler>>} */ (listenHandler),
452
+ ]),
649
453
  );
650
- return watch(innerVow, this.facets.rethrowUnlessMissingWatcher);
651
- },
652
- /** @param {ListenHandler} listenHandler */
653
- async removeListener(listenHandler) {
654
- const { listening, localAddr, protocolHandler } = this.state;
655
- listening.has(localAddr) || Fail`Port ${localAddr} is not listening`;
656
- listening.get(localAddr)[1] === listenHandler ||
657
- Fail`Port ${localAddr} handler to remove is not listening`;
658
- listening.delete(localAddr);
454
+ }
659
455
 
660
- const innerVow = watch(
661
- E(protocolHandler).onListenRemove(
662
- this.facets.port,
663
- localAddr,
664
- listenHandler,
665
- protocolHandler,
666
- ),
667
- this.facets.portRemoveListenerWatcher,
668
- { listenHandler },
669
- );
670
- return watch(innerVow, this.facets.rethrowUnlessMissingWatcher);
671
- },
672
- /**
673
- * @param {Endpoint} remotePort
674
- * @param {ConnectionHandler} connectionHandler
675
- */
676
- async connect(
677
- remotePort,
678
- connectionHandler = /** @type {any} */ (makeIncapable()),
679
- ) {
680
- const { revoked, localAddr, protocolImpl } = this.state;
681
-
682
- !revoked || Fail`Port ${localAddr} is revoked`;
683
- /** @type {Endpoint} */
684
- const dst = harden(remotePort);
685
- return watch(
686
- protocolImpl.outbound(this.facets.port, dst, connectionHandler),
687
- this.facets.portConnectWatcher,
688
- { revoked },
689
- );
690
- },
691
- async revoke() {
692
- const { revoked, localAddr } = this.state;
693
- const { protocolHandler } = this.state;
456
+ // ASSUME: that the listener defines onAccept.
694
457
 
695
- revoked !== RevokeState.REVOKED ||
696
- Fail`Port ${localAddr} is already revoked`;
458
+ const innerVow = watch(
459
+ E(protocolHandler).onListen(
460
+ this.facets.port,
461
+ localAddr,
462
+ listenHandler,
463
+ protocolHandler,
464
+ ),
465
+ this.facets.portAddListenerWatcher,
466
+ { listenHandler },
467
+ );
468
+ return watch(innerVow, this.facets.rethrowUnlessMissingWatcher);
469
+ },
470
+ /** @param {Remote<ListenHandler>} listenHandler */
471
+ async removeListener(listenHandler) {
472
+ const { listening, localAddr, protocolHandler } = this.state;
473
+ listening.has(localAddr) || Fail`Port ${localAddr} is not listening`;
474
+ listening.get(localAddr)[1] === listenHandler ||
475
+ Fail`Port ${localAddr} handler to remove is not listening`;
476
+ listening.delete(localAddr);
477
+
478
+ const innerVow = watch(
479
+ E(protocolHandler).onListenRemove(
480
+ this.facets.port,
481
+ localAddr,
482
+ listenHandler,
483
+ protocolHandler,
484
+ ),
485
+ this.facets.portRemoveListenerWatcher,
486
+ { listenHandler },
487
+ );
488
+ return watch(innerVow, this.facets.rethrowUnlessMissingWatcher);
489
+ },
490
+ /**
491
+ * @param {Endpoint} remotePort
492
+ * @param {Remote<ConnectionHandler>} [connectionHandler]
493
+ */
494
+ async connect(
495
+ remotePort,
496
+ connectionHandler = /** @type {Remote<ConnectionHandler>} */ (
497
+ makeIncapable()
498
+ ),
499
+ ) {
500
+ const { revoked, localAddr, protocolImpl } = this.state;
501
+
502
+ !revoked || Fail`Port ${localAddr} is revoked`;
503
+ /** @type {Endpoint} */
504
+ const dst = harden(remotePort);
505
+ return watch(
506
+ E(protocolImpl).outbound(this.facets.port, dst, connectionHandler),
507
+ this.facets.portConnectWatcher,
508
+ { revoked },
509
+ );
510
+ },
511
+ async revoke() {
512
+ const { revoked, localAddr } = this.state;
513
+ const { protocolHandler } = this.state;
697
514
 
698
- this.state.revoked = RevokeState.REVOKING;
515
+ revoked !== RevokeState.REVOKED ||
516
+ Fail`Port ${localAddr} is already revoked`;
699
517
 
700
- const revokeVow = watch(
701
- E(protocolHandler).onRevoke(
702
- this.facets.port,
703
- localAddr,
704
- protocolHandler,
705
- ),
706
- this.facets.portRevokeWatcher,
707
- );
518
+ this.state.revoked = RevokeState.REVOKING;
708
519
 
709
- return watch(revokeVow, this.facets.portRevokeCleanupWatcher);
710
- },
520
+ const revokeVow = watch(
521
+ E(protocolHandler).onRevoke(
522
+ this.facets.port,
523
+ localAddr,
524
+ protocolHandler,
525
+ ),
526
+ this.facets.portRevokeWatcher,
527
+ );
528
+
529
+ return watch(revokeVow, this.facets.portRevokeCleanupWatcher);
711
530
  },
712
- portAddListenerWatcher: {
713
- onFulfilled(_value, watcherContext) {
714
- const { listenHandler } = watcherContext;
715
- return E(listenHandler).onListen(this.facets.port, listenHandler);
716
- },
531
+ },
532
+ portAddListenerWatcher: {
533
+ onFulfilled(_value, watcherContext) {
534
+ const { listenHandler } = watcherContext;
535
+ return E(listenHandler).onListen(this.facets.port, listenHandler);
717
536
  },
718
- portRemoveListenerWatcher: {
719
- onFulfilled(_value, watcherContext) {
720
- const { listenHandler } = watcherContext;
721
- return E(listenHandler).onRemove(this.facets.port, listenHandler);
722
- },
537
+ },
538
+ portRemoveListenerWatcher: {
539
+ onFulfilled(_value, watcherContext) {
540
+ const { listenHandler } = watcherContext;
541
+ return E(listenHandler).onRemove(this.facets.port, listenHandler);
723
542
  },
724
- portConnectWatcher: {
725
- onFulfilled(conn, watchContext) {
726
- const { revoked } = watchContext;
727
- const { openConnections } = this.state;
728
-
729
- if (revoked) {
730
- void E(conn).close();
731
- } else {
732
- openConnections.add(conn);
733
- }
734
- return conn;
735
- },
543
+ },
544
+ portConnectWatcher: {
545
+ onFulfilled(conn, watchContext) {
546
+ const { revoked } = watchContext;
547
+ const { openConnections } = this.state;
548
+
549
+ if (revoked) {
550
+ void E(conn).close();
551
+ } else {
552
+ openConnections.add(conn);
553
+ }
554
+ return conn;
736
555
  },
737
- portRevokeWatcher: {
738
- onFulfilled(_value) {
739
- const { currentConnections, listening, localAddr } = this.state;
740
- const port = this.facets.port;
556
+ },
557
+ portRevokeWatcher: {
558
+ onFulfilled(_value) {
559
+ const { currentConnections, listening, localAddr } = this.state;
560
+ const port = this.facets.port;
741
561
 
742
- // Clean up everything we did.
743
- const values = [...currentConnections.get(port).values()];
562
+ // Clean up everything we did.
563
+ const values = [...currentConnections.get(port).values()];
744
564
 
745
- /** @type {import('@agoric/vow').Specimen[]} */
746
- const ps = [];
565
+ /** @type {import('@agoric/vow').Specimen[]} */
566
+ const ps = [];
747
567
 
748
- ps.push(
749
- ...values.map(conn =>
750
- watch(E(conn).close(), this.facets.sinkWatcher),
751
- ),
752
- );
568
+ ps.push(
569
+ ...values.map(conn =>
570
+ watch(E(conn).close(), this.facets.sinkWatcher),
571
+ ),
572
+ );
753
573
 
754
- if (listening.has(localAddr)) {
755
- const listener = listening.get(localAddr)[1];
756
- ps.push(port.removeListener(listener));
757
- }
574
+ if (listening.has(localAddr)) {
575
+ const listener = listening.get(localAddr)[1];
576
+ ps.push(port.removeListener(listener));
577
+ }
758
578
 
759
- return watch(allVows(ps), this.facets.rethrowUnlessMissingWatcher);
760
- },
579
+ return watch(allVows(ps), this.facets.rethrowUnlessMissingWatcher);
761
580
  },
762
- sinkWatcher: {
763
- onFulfilled() {
764
- return undefined;
765
- },
766
- onRejected() {
767
- return undefined;
768
- },
581
+ },
582
+ sinkWatcher: {
583
+ onFulfilled() {
584
+ return undefined;
769
585
  },
770
- portRevokeCleanupWatcher: {
771
- onFulfilled(_value) {
772
- const { currentConnections, boundPorts, localAddr } = this.state;
586
+ onRejected() {
587
+ return undefined;
588
+ },
589
+ },
590
+ portRevokeCleanupWatcher: {
591
+ onFulfilled(_value) {
592
+ const { currentConnections, boundPorts, localAddr } = this.state;
773
593
 
774
- this.state.revoked = RevokeState.REVOKED;
594
+ this.state.revoked = RevokeState.REVOKED;
775
595
 
776
- currentConnections.delete(this.facets.port);
777
- boundPorts.delete(localAddr);
778
- },
596
+ currentConnections.delete(this.facets.port);
597
+ boundPorts.delete(localAddr);
779
598
  },
780
- rethrowUnlessMissingWatcher: {
781
- onRejected(e) {
782
- rethrowUnlessMissing(e);
783
- },
599
+ },
600
+ rethrowUnlessMissingWatcher: {
601
+ onRejected(e) {
602
+ rethrowUnlessMissing(e);
784
603
  },
785
604
  },
786
- );
605
+ });
787
606
 
788
607
  const makePort = ({
789
608
  localAddr,
@@ -833,7 +652,7 @@ const prepareBinder = (zone, powers) => {
833
652
  {
834
653
  protocolImpl: Shape.ProtocolImplI,
835
654
  binder: M.interface('Binder', {
836
- bind: M.callWhen(Shape.Endpoint).returns(Shape2.Vow$(Shape.Port)),
655
+ bind: M.callWhen(Shape.Endpoint).returns(Shape.Vow$(Shape.Port)),
837
656
  }),
838
657
  binderInboundInstantiateWatcher: M.interface(
839
658
  'BinderInboundInstantiateWatcher',
@@ -889,10 +708,10 @@ const prepareBinder = (zone, powers) => {
889
708
  },
890
709
  /**
891
710
  * @param {object} opts
892
- * @param { MapStore<Port, SetStore<Closable>> } opts.currentConnections
711
+ * @param {MapStore<Port, SetStore<Closable>>} opts.currentConnections
893
712
  * @param {MapStore<string, Port>} opts.boundPorts
894
- * @param {MapStore<Endpoint, [Port, ListenHandler]>} opts.listening
895
- * @param {ProtocolHandler} opts.protocolHandler
713
+ * @param {MapStore<Endpoint, [Port, Remote<Required<ListenHandler>>]>} opts.listening
714
+ * @param {Remote<ProtocolHandler>} opts.protocolHandler
896
715
  */
897
716
  ({ currentConnections, boundPorts, listening, protocolHandler }) => {
898
717
  /** @type {SetStore<Connection>} */
@@ -937,7 +756,11 @@ const prepareBinder = (zone, powers) => {
937
756
  const [port] = listening.get(/** @type {string} **/ (listenPrefix));
938
757
 
939
758
  const innerVow = watch(
940
- E(protocolHandler).onInstantiate(
759
+ E(
760
+ /** @type {Remote<Required<ProtocolHandler>>} */ (
761
+ protocolHandler
762
+ ),
763
+ ).onInstantiate(
941
764
  /** @type {Port} **/ (port),
942
765
  prefixes[listenPrefixIndex],
943
766
  remoteAddr,
@@ -975,12 +798,11 @@ const prepareBinder = (zone, powers) => {
975
798
 
976
799
  // Allocate a local address.
977
800
  const instantiateInnerVow = watch(
978
- E(protocolHandler).onInstantiate(
979
- port,
980
- localAddr,
981
- remoteAddr,
982
- protocolHandler,
983
- ),
801
+ E(
802
+ /** @type {Remote<Required<ProtocolHandler>>} */ (
803
+ protocolHandler
804
+ ),
805
+ ).onInstantiate(port, localAddr, remoteAddr, protocolHandler),
984
806
  this.facets.binderOutboundInstantiateWatcher,
985
807
  {
986
808
  port,
@@ -1102,7 +924,11 @@ const prepareBinder = (zone, powers) => {
1102
924
  const [port] = listening.get(/** @type {string} */ (listenPrefix));
1103
925
 
1104
926
  const innerVow = watch(
1105
- E(protocolHandler).onInstantiate(
927
+ E(
928
+ /** @type {Remote<Required<ProtocolHandler>>} */ (
929
+ protocolHandler
930
+ ),
931
+ ).onInstantiate(
1106
932
  port,
1107
933
  prefixes[listenPrefixIndex],
1108
934
  remoteAddr,
@@ -1150,9 +976,13 @@ const prepareBinder = (zone, powers) => {
1150
976
 
1151
977
  return crossoverConnection(
1152
978
  zone,
1153
- lchandler,
979
+ /** @type {import('@agoric/vow').Remote<Required<ConnectionHandler>>} */ (
980
+ lchandler
981
+ ),
1154
982
  localAddr,
1155
- rchandler,
983
+ /** @type {import('@agoric/vow').Remote<Required<ConnectionHandler>>} */ (
984
+ rchandler
985
+ ),
1156
986
  remoteAddr,
1157
987
  makeConnection,
1158
988
  current,
@@ -1210,7 +1040,7 @@ const prepareBinder = (zone, powers) => {
1210
1040
  binderOutboundAcceptWatcher: {
1211
1041
  onFulfilled(attempt, watchContext) {
1212
1042
  const { handler } = watchContext;
1213
- return attempt.accept({ handler });
1043
+ return E(attempt).accept({ handler });
1214
1044
  },
1215
1045
  },
1216
1046
  binderBindGeneratePortWatcher: {
@@ -1238,7 +1068,7 @@ const prepareBinder = (zone, powers) => {
1238
1068
  const { port, localAddr } = watchContext;
1239
1069
  const { boundPorts, currentConnections } = this.state;
1240
1070
 
1241
- boundPorts.init(localAddr, harden(port));
1071
+ boundPorts.init(localAddr, port);
1242
1072
  currentConnections.init(
1243
1073
  port,
1244
1074
  zone.detached().setStore('connections'),
@@ -1313,7 +1143,7 @@ export const prepareNetworkProtocol = (zone, powers) => {
1313
1143
  const makeBinderKit = prepareBinder(zone, powers);
1314
1144
 
1315
1145
  /**
1316
- * @param {ProtocolHandler} protocolHandler
1146
+ * @param {Remote<ProtocolHandler>} protocolHandler
1317
1147
  * @returns {Protocol}
1318
1148
  */
1319
1149
  const makeNetworkProtocol = protocolHandler => {
@@ -1325,7 +1155,7 @@ export const prepareNetworkProtocol = (zone, powers) => {
1325
1155
  /** @type {MapStore<string, Port>} */
1326
1156
  const boundPorts = detached.mapStore('addrToPort');
1327
1157
 
1328
- /** @type {MapStore<Endpoint, [Port, ListenHandler]>} */
1158
+ /** @type {MapStore<Endpoint, [Port, Remote<Required<ListenHandler>>]>} */
1329
1159
  const listening = detached.mapStore('listening');
1330
1160
 
1331
1161
  const { binder, protocolImpl } = makeBinderKit({
@@ -1354,14 +1184,14 @@ export const prepareEchoConnectionKit = zone => {
1354
1184
  {
1355
1185
  handler: M.interface('ConnectionHandler', {
1356
1186
  onReceive: M.callWhen(
1357
- Shape2.Connection,
1358
- Shape2.Bytes,
1359
- Shape2.ConnectionHandler,
1187
+ Shape.Connection,
1188
+ Shape.Bytes,
1189
+ Shape.ConnectionHandler,
1360
1190
  )
1361
- .optional(Shape2.Opts)
1362
- .returns(Shape2.Data),
1363
- onClose: M.callWhen(Shape2.Connection)
1364
- .optional(M.any(), Shape2.ConnectionHandler)
1191
+ .optional(Shape.Opts)
1192
+ .returns(Shape.Data),
1193
+ onClose: M.callWhen(Shape.Connection)
1194
+ .optional(M.any(), Shape.ConnectionHandler)
1365
1195
  .returns(M.undefined()),
1366
1196
  }),
1367
1197
  listener: M.interface('Listener', {
@@ -1377,10 +1207,9 @@ export const prepareEchoConnectionKit = zone => {
1377
1207
  }),
1378
1208
  },
1379
1209
  () => {
1380
- /** @type {string | undefined} */
1381
- let closed;
1382
1210
  return {
1383
- closed,
1211
+ /** @type {string | undefined} */
1212
+ closed: undefined,
1384
1213
  };
1385
1214
  },
1386
1215
  {
@@ -1394,7 +1223,7 @@ export const prepareEchoConnectionKit = zone => {
1394
1223
  const { closed } = this.state;
1395
1224
 
1396
1225
  if (closed) {
1397
- throw closed;
1226
+ throw Error(closed);
1398
1227
  }
1399
1228
  return bytes;
1400
1229
  },
@@ -1415,7 +1244,7 @@ export const prepareEchoConnectionKit = zone => {
1415
1244
  },
1416
1245
  listener: {
1417
1246
  async onAccept(_port, _localAddr, _remoteAddr, _listenHandler) {
1418
- return harden(this.facets.handler);
1247
+ return this.facets.handler;
1419
1248
  },
1420
1249
  async onListen(port, _listenHandler) {
1421
1250
  console.debug(`listening on echo port: ${port}`);
@@ -1433,24 +1262,27 @@ export const prepareEchoConnectionKit = zone => {
1433
1262
  * @param {import('@agoric/base-zone').Zone} zone
1434
1263
  * @param {ReturnType<import('@agoric/vow').prepareVowTools>} powers
1435
1264
  */
1436
- export function prepareLoopbackProtocolHandler(zone, { watch }) {
1265
+ export function prepareLoopbackProtocolHandler(zone, { watch, allVows }) {
1437
1266
  const detached = zone.detached();
1438
1267
 
1268
+ /** @param {string} [instancePrefix] */
1269
+ const initHandler = (instancePrefix = 'nonce/') => {
1270
+ /** @type {MapStore<string, [Remote<Port>, Remote<Required<ListenHandler>>]>} */
1271
+ const listeners = detached.mapStore('localAddr');
1272
+
1273
+ return {
1274
+ listeners,
1275
+ portNonce: 0n,
1276
+ instancePrefix,
1277
+ instanceNonce: 0n,
1278
+ };
1279
+ };
1280
+
1439
1281
  const makeLoopbackProtocolHandlerKit = zone.exoClassKit(
1440
1282
  'ProtocolHandler',
1441
1283
  Shape.ProtocolHandlerI,
1442
1284
  /** @param {string} [instancePrefix] */
1443
- (instancePrefix = 'nonce/') => {
1444
- /** @type {MapStore<string, [Port, ListenHandler]>} */
1445
- const listeners = detached.mapStore('localAddr');
1446
-
1447
- return {
1448
- listeners,
1449
- portNonce: 0n,
1450
- instancePrefix,
1451
- instanceNonce: 0n,
1452
- };
1453
- },
1285
+ initHandler,
1454
1286
  {
1455
1287
  protocolHandler: {
1456
1288
  async onCreate(_impl, _protocolHandler) {
@@ -1463,13 +1295,13 @@ export function prepareLoopbackProtocolHandler(zone, { watch }) {
1463
1295
  async onBind(_port, _localAddr, _protocolHandler) {
1464
1296
  // noop, for now; Maybe handle a bind?
1465
1297
  },
1466
- async onConnect(
1467
- _port,
1468
- localAddr,
1469
- remoteAddr,
1470
- _chandler,
1471
- protocolHandler,
1472
- ) {
1298
+ /**
1299
+ * @param {*} _port
1300
+ * @param {Endpoint} localAddr
1301
+ * @param {Endpoint} remoteAddr
1302
+ * @returns {PromiseVow<AttemptDescription>}}
1303
+ */
1304
+ async onConnect(_port, localAddr, remoteAddr) {
1473
1305
  const { listeners } = this.state;
1474
1306
  const [lport, lhandler] = listeners.get(remoteAddr);
1475
1307
 
@@ -1479,11 +1311,11 @@ export function prepareLoopbackProtocolHandler(zone, { watch }) {
1479
1311
  );
1480
1312
 
1481
1313
  const instantiateInnerVow = watch(
1482
- E(protocolHandler).onInstantiate(
1314
+ E(this.facets.protocolHandler).onInstantiate(
1483
1315
  lport,
1484
1316
  remoteAddr,
1485
1317
  localAddr,
1486
- protocolHandler,
1318
+ this.facets.protocolHandler,
1487
1319
  ),
1488
1320
  this.facets.protocolHandlerInstantiateWatcher,
1489
1321
  );
@@ -1493,7 +1325,7 @@ export function prepareLoopbackProtocolHandler(zone, { watch }) {
1493
1325
  this.facets.rethrowUnlessMissingWatcher,
1494
1326
  );
1495
1327
  return watch(
1496
- Promise.all([acceptVow, instantiateVow]),
1328
+ allVows([acceptVow, instantiateVow]),
1497
1329
  this.facets.protocolHandlerConnectWatcher,
1498
1330
  );
1499
1331
  },
@@ -1510,16 +1342,30 @@ export function prepareLoopbackProtocolHandler(zone, { watch }) {
1510
1342
  if (listeners.has(localAddr)) {
1511
1343
  const lhandler = listeners.get(localAddr)[1];
1512
1344
  if (lhandler !== listenHandler) {
1513
- listeners.set(localAddr, [port, listenHandler]);
1345
+ listeners.set(
1346
+ localAddr,
1347
+ harden([
1348
+ port,
1349
+ /** @type {Remote<Required<ListenHandler>>} */ (
1350
+ listenHandler
1351
+ ),
1352
+ ]),
1353
+ );
1514
1354
  }
1515
1355
  } else {
1516
- listeners.init(localAddr, harden([port, listenHandler]));
1356
+ listeners.init(
1357
+ localAddr,
1358
+ harden([
1359
+ port,
1360
+ /** @type {Remote<Required<ListenHandler>>} */ (listenHandler),
1361
+ ]),
1362
+ );
1517
1363
  }
1518
1364
  },
1519
1365
  /**
1520
- * @param {Port} port
1366
+ * @param {Remote<Port>} port
1521
1367
  * @param {Endpoint} localAddr
1522
- * @param {ListenHandler} listenHandler
1368
+ * @param {Remote<ListenHandler>} listenHandler
1523
1369
  * @param {*} _protocolHandler
1524
1370
  */
1525
1371
  async onListenRemove(port, localAddr, listenHandler, _protocolHandler) {