@agoric/network 0.1.1-dev-5676146.0 → 0.1.1-dev-e7e7c67.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/package.json +9 -9
- package/src/network.d.ts +99 -35
- package/src/network.d.ts.map +1 -1
- package/src/network.js +1008 -462
- package/src/router.d.ts +5 -0
- package/src/router.d.ts.map +1 -1
- package/src/types.d.ts +1 -1
- package/src/types.d.ts.map +1 -1
- package/src/types.js +1 -1
package/src/network.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
import { E } from '@endo/far';
|
|
4
4
|
import { M } from '@endo/patterns';
|
|
5
5
|
import { Fail } from '@agoric/assert';
|
|
6
|
-
import { whileTrue } from '@agoric/internal';
|
|
7
6
|
import { toBytes } from './bytes.js';
|
|
8
7
|
|
|
9
8
|
import '@agoric/store/exported.js';
|
|
@@ -23,14 +22,12 @@ const Shape1 = /** @type {const} */ ({
|
|
|
23
22
|
Data: M.string(),
|
|
24
23
|
Bytes: M.string(),
|
|
25
24
|
Endpoint: M.string(),
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
Vow: M.any(),
|
|
33
|
-
|
|
25
|
+
Vow: M.tagged(
|
|
26
|
+
'Vow',
|
|
27
|
+
harden({
|
|
28
|
+
vowV0: M.remotable('VowV0'),
|
|
29
|
+
}),
|
|
30
|
+
),
|
|
34
31
|
ConnectionHandler: M.remotable('ConnectionHandler'),
|
|
35
32
|
Connection: M.remotable('Connection'),
|
|
36
33
|
InboundAttempt: M.remotable('InboundAttempt'),
|
|
@@ -53,78 +50,146 @@ const Shape2 = /** @type {const} */ ({
|
|
|
53
50
|
|
|
54
51
|
export const Shape = /** @type {const} */ harden({
|
|
55
52
|
...Shape2,
|
|
56
|
-
ConnectionI:
|
|
57
|
-
|
|
58
|
-
.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
),
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
+
},
|
|
88
181
|
),
|
|
89
|
-
|
|
90
|
-
|
|
182
|
+
protocolHandlerConnectWatcher: M.interface(
|
|
183
|
+
'ProtocolHandlerConnectWatcher',
|
|
184
|
+
{
|
|
185
|
+
onFulfilled: M.call(M.any()).rest(M.any()).returns(),
|
|
186
|
+
},
|
|
91
187
|
),
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
onListen: M.callWhen(
|
|
98
|
-
Shape2.Port,
|
|
99
|
-
Shape2.Endpoint,
|
|
100
|
-
Shape2.ListenHandler,
|
|
101
|
-
Shape2.ProtocolHandler,
|
|
102
|
-
).returns(Shape2.Vow$(M.undefined())),
|
|
103
|
-
onListenRemove: M.callWhen(
|
|
104
|
-
Shape2.Port,
|
|
105
|
-
Shape2.Endpoint,
|
|
106
|
-
Shape2.ListenHandler,
|
|
107
|
-
Shape2.ProtocolHandler,
|
|
108
|
-
).returns(Shape2.Vow$(M.undefined())),
|
|
109
|
-
onInstantiate: M.callWhen(
|
|
110
|
-
Shape2.Port,
|
|
111
|
-
Shape2.Endpoint,
|
|
112
|
-
Shape2.Endpoint,
|
|
113
|
-
Shape2.ProtocolHandler,
|
|
114
|
-
).returns(Shape2.Vow$(Shape2.Endpoint)),
|
|
115
|
-
onConnect: M.callWhen(
|
|
116
|
-
Shape2.Port,
|
|
117
|
-
Shape2.Endpoint,
|
|
118
|
-
Shape2.Endpoint,
|
|
119
|
-
Shape2.ConnectionHandler,
|
|
120
|
-
Shape2.ProtocolHandler,
|
|
121
|
-
).returns(Shape2.Vow$(Shape2.AttemptDescription)),
|
|
122
|
-
onRevoke: M.callWhen(
|
|
123
|
-
Shape2.Port,
|
|
124
|
-
Shape2.Endpoint,
|
|
125
|
-
Shape2.ProtocolHandler,
|
|
126
|
-
).returns(Shape2.Vow$(M.undefined())),
|
|
127
|
-
}),
|
|
188
|
+
rethrowUnlessMissingWatcher: M.interface('RethrowUnlessMissingWatcher', {
|
|
189
|
+
onRejected: M.call(M.any()).rest(M.any()).returns(M.any()),
|
|
190
|
+
}),
|
|
191
|
+
},
|
|
192
|
+
|
|
128
193
|
ProtocolImplI: M.interface('ProtocolImpl', {
|
|
129
194
|
bind: M.callWhen(Shape2.Endpoint).returns(Shape2.Vow$(Shape2.Port)),
|
|
130
195
|
inbound: M.callWhen(Shape2.Endpoint, Shape2.Endpoint).returns(
|
|
@@ -183,8 +248,8 @@ export function getPrefixes(addr) {
|
|
|
183
248
|
* @param {import('@agoric/base-zone').Zone} zone
|
|
184
249
|
* @param {ReturnType<import('@agoric/vow').prepareVowTools>} powers
|
|
185
250
|
*/
|
|
186
|
-
const prepareHalfConnection = (zone, {
|
|
187
|
-
const
|
|
251
|
+
const prepareHalfConnection = (zone, { watch }) => {
|
|
252
|
+
const makeHalfConnectionKit = zone.exoClassKit(
|
|
188
253
|
'Connection',
|
|
189
254
|
Shape.ConnectionI,
|
|
190
255
|
/** @param {ConnectionOpts} opts */
|
|
@@ -203,47 +268,81 @@ const prepareHalfConnection = (zone, { when }) => {
|
|
|
203
268
|
};
|
|
204
269
|
},
|
|
205
270
|
{
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
handlers[l]
|
|
241
|
-
|
|
242
|
-
|
|
271
|
+
connection: {
|
|
272
|
+
getLocalAddress() {
|
|
273
|
+
const { addrs, l } = this.state;
|
|
274
|
+
return addrs[l];
|
|
275
|
+
},
|
|
276
|
+
getRemoteAddress() {
|
|
277
|
+
const { addrs, r } = this.state;
|
|
278
|
+
return addrs[r];
|
|
279
|
+
},
|
|
280
|
+
/** @param {Data} packetBytes */
|
|
281
|
+
async send(packetBytes) {
|
|
282
|
+
const { closed, handlers, r, conns } = this.state;
|
|
283
|
+
if (closed) {
|
|
284
|
+
throw closed;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const innerVow = watch(
|
|
288
|
+
E(handlers[r]).onReceive(
|
|
289
|
+
conns.get(r),
|
|
290
|
+
toBytes(packetBytes),
|
|
291
|
+
handlers[r],
|
|
292
|
+
),
|
|
293
|
+
this.facets.openConnectionAckWatcher,
|
|
294
|
+
);
|
|
295
|
+
return watch(innerVow, this.facets.rethrowUnlessMissingWatcher);
|
|
296
|
+
},
|
|
297
|
+
async close() {
|
|
298
|
+
const { closed, current, conns, l, handlers } = this.state;
|
|
299
|
+
if (closed) {
|
|
300
|
+
throw Error(closed);
|
|
301
|
+
}
|
|
302
|
+
this.state.closed = 'Connection closed';
|
|
303
|
+
current.delete(conns.get(l));
|
|
304
|
+
const innerVow = watch(
|
|
305
|
+
E(this.state.handlers[l]).onClose(
|
|
306
|
+
conns.get(l),
|
|
307
|
+
undefined,
|
|
308
|
+
handlers[l],
|
|
309
|
+
),
|
|
310
|
+
this.facets.sinkWatcher,
|
|
311
|
+
);
|
|
312
|
+
|
|
313
|
+
return watch(innerVow, this.facets.rethrowUnlessMissingWatcher);
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
openConnectionAckWatcher: {
|
|
317
|
+
onFulfilled(ack) {
|
|
318
|
+
return toBytes(ack || '');
|
|
319
|
+
},
|
|
320
|
+
},
|
|
321
|
+
rethrowUnlessMissingWatcher: {
|
|
322
|
+
onRejected(e) {
|
|
323
|
+
rethrowUnlessMissing(e);
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
sinkWatcher: {
|
|
327
|
+
onFulfilled(_value) {
|
|
328
|
+
return undefined;
|
|
329
|
+
},
|
|
243
330
|
},
|
|
244
331
|
},
|
|
245
332
|
);
|
|
246
333
|
|
|
334
|
+
const makeHalfConnection = ({ addrs, handlers, conns, current, l, r }) => {
|
|
335
|
+
const { connection } = makeHalfConnectionKit({
|
|
336
|
+
addrs,
|
|
337
|
+
handlers,
|
|
338
|
+
conns,
|
|
339
|
+
current,
|
|
340
|
+
l,
|
|
341
|
+
r,
|
|
342
|
+
});
|
|
343
|
+
return harden(connection);
|
|
344
|
+
};
|
|
345
|
+
|
|
247
346
|
return makeHalfConnection;
|
|
248
347
|
};
|
|
249
348
|
|
|
@@ -308,8 +407,8 @@ export const crossoverConnection = (
|
|
|
308
407
|
* @param {(opts: ConnectionOpts) => Connection} makeConnection
|
|
309
408
|
* @param {ReturnType<import('@agoric/vow').prepareVowTools>} powers
|
|
310
409
|
*/
|
|
311
|
-
const prepareInboundAttempt = (zone, makeConnection, {
|
|
312
|
-
const
|
|
410
|
+
const prepareInboundAttempt = (zone, makeConnection, { watch }) => {
|
|
411
|
+
const makeInboundAttemptKit = zone.exoClassKit(
|
|
313
412
|
'InboundAttempt',
|
|
314
413
|
Shape.InboundAttemptI,
|
|
315
414
|
/**
|
|
@@ -340,75 +439,121 @@ const prepareInboundAttempt = (zone, makeConnection, { when }) => {
|
|
|
340
439
|
};
|
|
341
440
|
},
|
|
342
441
|
{
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
442
|
+
inboundAttempt: {
|
|
443
|
+
getLocalAddress() {
|
|
444
|
+
// Return address metadata.
|
|
445
|
+
return this.state.localAddr;
|
|
446
|
+
},
|
|
447
|
+
getRemoteAddress() {
|
|
448
|
+
return this.state.remoteAddr;
|
|
449
|
+
},
|
|
450
|
+
async close() {
|
|
451
|
+
const { consummated, localAddr, remoteAddr } = this.state;
|
|
452
|
+
const { listening, listenPrefix, currentConnections } = this.state;
|
|
453
|
+
|
|
454
|
+
if (consummated) {
|
|
455
|
+
throw Error(consummated);
|
|
456
|
+
}
|
|
457
|
+
this.state.consummated = 'Already closed';
|
|
458
|
+
|
|
459
|
+
const [port, listener] = listening.get(listenPrefix);
|
|
460
|
+
|
|
461
|
+
const current = currentConnections.get(port);
|
|
462
|
+
current.delete(this.facets.inboundAttempt);
|
|
463
|
+
|
|
464
|
+
const innerVow = watch(
|
|
465
|
+
E(listener).onReject(port, localAddr, remoteAddr, listener),
|
|
466
|
+
this.facets.sinkWatcher,
|
|
467
|
+
);
|
|
468
|
+
|
|
469
|
+
return watch(innerVow, this.facets.rethrowUnlessMissingWatcher);
|
|
470
|
+
},
|
|
471
|
+
/**
|
|
472
|
+
* @param {object} opts
|
|
473
|
+
* @param {string} [opts.localAddress]
|
|
474
|
+
* @param {string} [opts.remoteAddress]
|
|
475
|
+
* @param {ConnectionHandler} opts.handler
|
|
476
|
+
*/
|
|
477
|
+
async accept({ localAddress, remoteAddress, handler: rchandler }) {
|
|
478
|
+
const { consummated, localAddr, remoteAddr } = this.state;
|
|
479
|
+
const { listening, listenPrefix, currentConnections } = this.state;
|
|
480
|
+
if (consummated) {
|
|
481
|
+
throw Error(consummated);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
if (localAddress === undefined) {
|
|
485
|
+
localAddress = localAddr;
|
|
486
|
+
}
|
|
487
|
+
this.state.consummated = `${localAddress} Already accepted`;
|
|
488
|
+
|
|
489
|
+
if (remoteAddress === undefined) {
|
|
490
|
+
remoteAddress = remoteAddr;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
const [port, listener] = listening.get(listenPrefix);
|
|
494
|
+
const current = currentConnections.get(port);
|
|
495
|
+
|
|
496
|
+
current.delete(this.facets.inboundAttempt);
|
|
497
|
+
|
|
498
|
+
return watch(
|
|
499
|
+
E(listener).onAccept(port, localAddress, remoteAddress, listener),
|
|
500
|
+
this.facets.inboundAttemptAcceptWatcher,
|
|
501
|
+
{
|
|
502
|
+
localAddress,
|
|
503
|
+
rchandler,
|
|
504
|
+
remoteAddress,
|
|
505
|
+
current,
|
|
506
|
+
},
|
|
507
|
+
);
|
|
508
|
+
},
|
|
509
|
+
},
|
|
510
|
+
inboundAttemptAcceptWatcher: {
|
|
511
|
+
onFulfilled(lchandler, watchContext) {
|
|
512
|
+
const { localAddress, rchandler, remoteAddress, current } =
|
|
513
|
+
watchContext;
|
|
514
|
+
|
|
515
|
+
return crossoverConnection(
|
|
516
|
+
zone,
|
|
517
|
+
lchandler,
|
|
518
|
+
localAddress,
|
|
519
|
+
rchandler,
|
|
520
|
+
remoteAddress,
|
|
521
|
+
makeConnection,
|
|
522
|
+
current,
|
|
523
|
+
)[1];
|
|
524
|
+
},
|
|
525
|
+
},
|
|
526
|
+
rethrowUnlessMissingWatcher: {
|
|
527
|
+
onRejected(e) {
|
|
528
|
+
rethrowUnlessMissing(e);
|
|
529
|
+
},
|
|
530
|
+
},
|
|
531
|
+
sinkWatcher: {
|
|
532
|
+
onFulfilled(_value) {
|
|
533
|
+
return undefined;
|
|
534
|
+
},
|
|
408
535
|
},
|
|
409
536
|
},
|
|
410
537
|
);
|
|
411
538
|
|
|
539
|
+
const makeInboundAttempt = ({
|
|
540
|
+
localAddr,
|
|
541
|
+
remoteAddr,
|
|
542
|
+
currentConnections,
|
|
543
|
+
listenPrefix,
|
|
544
|
+
listening,
|
|
545
|
+
}) => {
|
|
546
|
+
const { inboundAttempt } = makeInboundAttemptKit({
|
|
547
|
+
localAddr,
|
|
548
|
+
remoteAddr,
|
|
549
|
+
currentConnections,
|
|
550
|
+
listenPrefix,
|
|
551
|
+
listening,
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
return harden(inboundAttempt);
|
|
555
|
+
};
|
|
556
|
+
|
|
412
557
|
return makeInboundAttempt;
|
|
413
558
|
};
|
|
414
559
|
|
|
@@ -423,10 +568,12 @@ const RevokeState = /** @type {const} */ ({
|
|
|
423
568
|
* @param {import('@agoric/zone').Zone} zone
|
|
424
569
|
* @param {ReturnType<import('@agoric/vow').prepareVowTools>} powers
|
|
425
570
|
*/
|
|
426
|
-
const preparePort = (zone,
|
|
571
|
+
const preparePort = (zone, powers) => {
|
|
427
572
|
const makeIncapable = zone.exoClass('Incapable', undefined, () => ({}), {});
|
|
428
573
|
|
|
429
|
-
const
|
|
574
|
+
const { watch, allVows } = powers;
|
|
575
|
+
|
|
576
|
+
const makePortKit = zone.exoClassKit(
|
|
430
577
|
'Port',
|
|
431
578
|
Shape.PortI,
|
|
432
579
|
/**
|
|
@@ -461,114 +608,204 @@ const preparePort = (zone, { when }) => {
|
|
|
461
608
|
};
|
|
462
609
|
},
|
|
463
610
|
{
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
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
|
+
);
|
|
480
636
|
}
|
|
481
|
-
listening.set(localAddr, [this.self, listenHandler]);
|
|
482
|
-
E(lhandler).onRemove(lport, lhandler).catch(rethrowUnlessMissing);
|
|
483
|
-
} else {
|
|
484
|
-
listening.init(localAddr, harden([this.self, listenHandler]));
|
|
485
|
-
}
|
|
486
637
|
|
|
487
|
-
|
|
638
|
+
// ASSUME: that the listener defines onAccept.
|
|
488
639
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
this.state;
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
640
|
+
const innerVow = watch(
|
|
641
|
+
E(protocolHandler).onListen(
|
|
642
|
+
this.facets.port,
|
|
643
|
+
localAddr,
|
|
644
|
+
listenHandler,
|
|
645
|
+
protocolHandler,
|
|
646
|
+
),
|
|
647
|
+
this.facets.portAddListenerWatcher,
|
|
648
|
+
{ listenHandler },
|
|
649
|
+
);
|
|
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);
|
|
659
|
+
|
|
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;
|
|
694
|
+
|
|
695
|
+
revoked !== RevokeState.REVOKED ||
|
|
696
|
+
Fail`Port ${localAddr} is already revoked`;
|
|
697
|
+
|
|
698
|
+
this.state.revoked = RevokeState.REVOKING;
|
|
699
|
+
|
|
700
|
+
const revokeVow = watch(
|
|
701
|
+
E(protocolHandler).onRevoke(
|
|
702
|
+
this.facets.port,
|
|
703
|
+
localAddr,
|
|
704
|
+
protocolHandler,
|
|
705
|
+
),
|
|
706
|
+
this.facets.portRevokeWatcher,
|
|
707
|
+
);
|
|
708
|
+
|
|
709
|
+
return watch(revokeVow, this.facets.portRevokeCleanupWatcher);
|
|
710
|
+
},
|
|
711
|
+
},
|
|
712
|
+
portAddListenerWatcher: {
|
|
713
|
+
onFulfilled(_value, watcherContext) {
|
|
714
|
+
const { listenHandler } = watcherContext;
|
|
715
|
+
return E(listenHandler).onListen(this.facets.port, listenHandler);
|
|
716
|
+
},
|
|
717
|
+
},
|
|
718
|
+
portRemoveListenerWatcher: {
|
|
719
|
+
onFulfilled(_value, watcherContext) {
|
|
720
|
+
const { listenHandler } = watcherContext;
|
|
721
|
+
return E(listenHandler).onRemove(this.facets.port, listenHandler);
|
|
722
|
+
},
|
|
723
|
+
},
|
|
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
|
+
},
|
|
736
|
+
},
|
|
737
|
+
portRevokeWatcher: {
|
|
738
|
+
onFulfilled(_value) {
|
|
739
|
+
const { currentConnections, listening, localAddr } = this.state;
|
|
740
|
+
const port = this.facets.port;
|
|
741
|
+
|
|
742
|
+
// Clean up everything we did.
|
|
743
|
+
const values = [...currentConnections.get(port).values()];
|
|
744
|
+
|
|
745
|
+
/** @type {import('@agoric/vow').Specimen[]} */
|
|
746
|
+
const ps = [];
|
|
747
|
+
|
|
748
|
+
ps.push(
|
|
749
|
+
...values.map(conn =>
|
|
750
|
+
watch(E(conn).close(), this.facets.sinkWatcher),
|
|
751
|
+
),
|
|
752
|
+
);
|
|
753
|
+
|
|
754
|
+
if (listening.has(localAddr)) {
|
|
755
|
+
const listener = listening.get(localAddr)[1];
|
|
756
|
+
ps.push(port.removeListener(listener));
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
return watch(allVows(ps), this.facets.rethrowUnlessMissingWatcher);
|
|
760
|
+
},
|
|
761
|
+
},
|
|
762
|
+
sinkWatcher: {
|
|
763
|
+
onFulfilled() {
|
|
764
|
+
return undefined;
|
|
765
|
+
},
|
|
766
|
+
onRejected() {
|
|
767
|
+
return undefined;
|
|
768
|
+
},
|
|
769
|
+
},
|
|
770
|
+
portRevokeCleanupWatcher: {
|
|
771
|
+
onFulfilled(_value) {
|
|
772
|
+
const { currentConnections, boundPorts, localAddr } = this.state;
|
|
773
|
+
|
|
774
|
+
this.state.revoked = RevokeState.REVOKED;
|
|
775
|
+
|
|
776
|
+
currentConnections.delete(this.facets.port);
|
|
777
|
+
boundPorts.delete(localAddr);
|
|
778
|
+
},
|
|
779
|
+
},
|
|
780
|
+
rethrowUnlessMissingWatcher: {
|
|
781
|
+
onRejected(e) {
|
|
782
|
+
rethrowUnlessMissing(e);
|
|
783
|
+
},
|
|
568
784
|
},
|
|
569
785
|
},
|
|
570
786
|
);
|
|
571
787
|
|
|
788
|
+
const makePort = ({
|
|
789
|
+
localAddr,
|
|
790
|
+
listening,
|
|
791
|
+
openConnections,
|
|
792
|
+
currentConnections,
|
|
793
|
+
boundPorts,
|
|
794
|
+
protocolHandler,
|
|
795
|
+
protocolImpl,
|
|
796
|
+
}) => {
|
|
797
|
+
const { port } = makePortKit({
|
|
798
|
+
localAddr,
|
|
799
|
+
listening,
|
|
800
|
+
openConnections,
|
|
801
|
+
currentConnections,
|
|
802
|
+
boundPorts,
|
|
803
|
+
protocolHandler,
|
|
804
|
+
protocolImpl,
|
|
805
|
+
});
|
|
806
|
+
return harden(port);
|
|
807
|
+
};
|
|
808
|
+
|
|
572
809
|
return makePort;
|
|
573
810
|
};
|
|
574
811
|
|
|
@@ -578,21 +815,76 @@ const preparePort = (zone, { when }) => {
|
|
|
578
815
|
*/
|
|
579
816
|
const prepareBinder = (zone, powers) => {
|
|
580
817
|
const makeConnection = prepareHalfConnection(zone, powers);
|
|
581
|
-
|
|
818
|
+
|
|
819
|
+
const { watch } = powers;
|
|
820
|
+
|
|
582
821
|
const makeInboundAttempt = prepareInboundAttempt(
|
|
583
822
|
zone,
|
|
584
823
|
makeConnection,
|
|
585
824
|
powers,
|
|
586
825
|
);
|
|
826
|
+
|
|
587
827
|
const makePort = preparePort(zone, powers);
|
|
828
|
+
|
|
588
829
|
const detached = zone.detached();
|
|
589
830
|
|
|
590
|
-
const
|
|
831
|
+
const makeFullBinderKit = zone.exoClassKit(
|
|
591
832
|
'binder',
|
|
592
833
|
{
|
|
593
834
|
protocolImpl: Shape.ProtocolImplI,
|
|
594
835
|
binder: M.interface('Binder', {
|
|
595
|
-
bind: M.callWhen(Shape.Endpoint).returns(Shape.Port),
|
|
836
|
+
bind: M.callWhen(Shape.Endpoint).returns(Shape2.Vow$(Shape.Port)),
|
|
837
|
+
}),
|
|
838
|
+
binderInboundInstantiateWatcher: M.interface(
|
|
839
|
+
'BinderInboundInstantiateWatcher',
|
|
840
|
+
{
|
|
841
|
+
onFulfilled: M.call(M.any()).rest(M.any()).returns(M.any()),
|
|
842
|
+
},
|
|
843
|
+
),
|
|
844
|
+
binderInboundInstantiateCatchWatcher: M.interface(
|
|
845
|
+
'BinderInboundInstantiateCatchWatcher',
|
|
846
|
+
{
|
|
847
|
+
onRejected: M.call(M.any()).rest(M.any()).returns(M.any()),
|
|
848
|
+
},
|
|
849
|
+
),
|
|
850
|
+
binderOutboundInstantiateWatcher: M.interface(
|
|
851
|
+
'BinderOutboundInstantiateWatcher',
|
|
852
|
+
{
|
|
853
|
+
onFulfilled: M.call(M.any()).rest(M.any()).returns(M.any()),
|
|
854
|
+
},
|
|
855
|
+
),
|
|
856
|
+
binderOutboundConnectWatcher: M.interface(
|
|
857
|
+
'BinderOutboundConnectWatcher',
|
|
858
|
+
{
|
|
859
|
+
onFulfilled: M.call(M.any()).rest(M.any()).returns(M.any()),
|
|
860
|
+
},
|
|
861
|
+
),
|
|
862
|
+
binderOutboundCatchWatcher: M.interface('BinderOutboundCatchWatcher', {
|
|
863
|
+
onRejected: M.call(M.any()).rest(M.any()).returns(M.any()),
|
|
864
|
+
}),
|
|
865
|
+
binderOutboundInboundWatcher: M.interface(
|
|
866
|
+
'BinderOutboundInboundWatcher',
|
|
867
|
+
{
|
|
868
|
+
onFulfilled: M.call(M.any()).rest(M.any()).returns(M.any()),
|
|
869
|
+
},
|
|
870
|
+
),
|
|
871
|
+
binderOutboundAcceptWatcher: M.interface('BinderOutboundAcceptWatcher', {
|
|
872
|
+
onFulfilled: M.call(M.any()).rest(M.any()).returns(M.any()),
|
|
873
|
+
}),
|
|
874
|
+
binderBindGeneratePortWatcher: M.interface(
|
|
875
|
+
'BinderBindGeneratePortWatcher',
|
|
876
|
+
{
|
|
877
|
+
onFulfilled: M.call(M.any()).rest(M.any()).returns(M.any()),
|
|
878
|
+
},
|
|
879
|
+
),
|
|
880
|
+
binderPortWatcher: M.interface('BinderPortWatcher', {
|
|
881
|
+
onFulfilled: M.call(M.any()).rest(M.any()).returns(M.any()),
|
|
882
|
+
}),
|
|
883
|
+
binderBindWatcher: M.interface('BinderBindWatcher', {
|
|
884
|
+
onFulfilled: M.call(M.any()).rest(M.any()).returns(M.any()),
|
|
885
|
+
}),
|
|
886
|
+
rethrowUnlessMissingWatcher: M.interface('RethrowUnlessMissingWatcher', {
|
|
887
|
+
onRejected: M.call(M.any()).rest(M.any()).returns(M.any()),
|
|
596
888
|
}),
|
|
597
889
|
},
|
|
598
890
|
/**
|
|
@@ -613,8 +905,6 @@ const prepareBinder = (zone, powers) => {
|
|
|
613
905
|
revoked: RevokeState.NOT_REVOKED,
|
|
614
906
|
openConnections,
|
|
615
907
|
protocolHandler,
|
|
616
|
-
/** @type {Endpoint | undefined} */
|
|
617
|
-
localAddr: undefined,
|
|
618
908
|
};
|
|
619
909
|
},
|
|
620
910
|
{
|
|
@@ -624,49 +914,54 @@ const prepareBinder = (zone, powers) => {
|
|
|
624
914
|
* @param {Endpoint} remoteAddr
|
|
625
915
|
*/
|
|
626
916
|
async inbound(listenAddr, remoteAddr) {
|
|
627
|
-
const { listening, protocolHandler
|
|
917
|
+
const { listening, protocolHandler } = this.state;
|
|
918
|
+
|
|
919
|
+
const prefixes = getPrefixes(listenAddr);
|
|
920
|
+
let listenPrefixIndex = 0;
|
|
921
|
+
let listenPrefix;
|
|
628
922
|
|
|
629
|
-
|
|
630
|
-
|
|
923
|
+
while (listenPrefixIndex < prefixes.length) {
|
|
924
|
+
listenPrefix = prefixes[listenPrefixIndex];
|
|
631
925
|
if (!listening.has(listenPrefix)) {
|
|
926
|
+
listenPrefixIndex += 1;
|
|
632
927
|
continue;
|
|
633
928
|
}
|
|
634
|
-
const [port, _] = listening.get(listenPrefix);
|
|
635
|
-
let localAddr;
|
|
636
|
-
|
|
637
|
-
await (async () => {
|
|
638
|
-
// See if our protocol is willing to receive this connection.
|
|
639
|
-
const localInstance = await when(
|
|
640
|
-
E(protocolHandler).onInstantiate(
|
|
641
|
-
port,
|
|
642
|
-
listenPrefix,
|
|
643
|
-
remoteAddr,
|
|
644
|
-
protocolHandler,
|
|
645
|
-
),
|
|
646
|
-
).catch(rethrowUnlessMissing);
|
|
647
|
-
localAddr = localInstance
|
|
648
|
-
? `${listenAddr}/${localInstance}`
|
|
649
|
-
: listenAddr;
|
|
650
|
-
})().catch(e => {
|
|
651
|
-
lastFailure = e;
|
|
652
|
-
});
|
|
653
|
-
if (!localAddr) {
|
|
654
|
-
continue;
|
|
655
|
-
}
|
|
656
|
-
// We have a legitimate inbound attempt.
|
|
657
|
-
const current = currentConnections.get(port);
|
|
658
|
-
const inboundAttempt = makeInboundAttempt({
|
|
659
|
-
localAddr,
|
|
660
|
-
remoteAddr,
|
|
661
|
-
currentConnections,
|
|
662
|
-
listenPrefix,
|
|
663
|
-
listening,
|
|
664
|
-
});
|
|
665
929
|
|
|
666
|
-
|
|
667
|
-
return inboundAttempt;
|
|
930
|
+
break;
|
|
668
931
|
}
|
|
669
|
-
|
|
932
|
+
|
|
933
|
+
if (listenPrefixIndex >= prefixes.length) {
|
|
934
|
+
throw Error(`No listeners for ${listenAddr}`);
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
const [port] = listening.get(/** @type {string} **/ (listenPrefix));
|
|
938
|
+
|
|
939
|
+
const innerVow = watch(
|
|
940
|
+
E(protocolHandler).onInstantiate(
|
|
941
|
+
/** @type {Port} **/ (port),
|
|
942
|
+
prefixes[listenPrefixIndex],
|
|
943
|
+
remoteAddr,
|
|
944
|
+
protocolHandler,
|
|
945
|
+
),
|
|
946
|
+
this.facets.binderInboundInstantiateWatcher,
|
|
947
|
+
{
|
|
948
|
+
listenAddr,
|
|
949
|
+
remoteAddr,
|
|
950
|
+
port,
|
|
951
|
+
listenPrefixIndex,
|
|
952
|
+
},
|
|
953
|
+
);
|
|
954
|
+
|
|
955
|
+
return watch(
|
|
956
|
+
innerVow,
|
|
957
|
+
this.facets.binderInboundInstantiateCatchWatcher,
|
|
958
|
+
{
|
|
959
|
+
listenPrefixIndex,
|
|
960
|
+
listenAddr,
|
|
961
|
+
remoteAddr,
|
|
962
|
+
lastFailure: Error(`No listeners for ${listenAddr}`),
|
|
963
|
+
},
|
|
964
|
+
);
|
|
670
965
|
},
|
|
671
966
|
/**
|
|
672
967
|
* @param {Port} port
|
|
@@ -674,101 +969,293 @@ const prepareBinder = (zone, powers) => {
|
|
|
674
969
|
* @param {ConnectionHandler} lchandler
|
|
675
970
|
*/
|
|
676
971
|
async outbound(port, remoteAddr, lchandler) {
|
|
677
|
-
const { protocolHandler
|
|
972
|
+
const { protocolHandler } = this.state;
|
|
678
973
|
|
|
679
974
|
const localAddr = await E(port).getLocalAddress();
|
|
680
975
|
|
|
681
976
|
// Allocate a local address.
|
|
682
|
-
const
|
|
977
|
+
const instantiateInnerVow = watch(
|
|
683
978
|
E(protocolHandler).onInstantiate(
|
|
684
979
|
port,
|
|
685
980
|
localAddr,
|
|
686
981
|
remoteAddr,
|
|
687
982
|
protocolHandler,
|
|
688
983
|
),
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
984
|
+
this.facets.binderOutboundInstantiateWatcher,
|
|
985
|
+
{
|
|
986
|
+
port,
|
|
987
|
+
localAddr,
|
|
988
|
+
remoteAddr,
|
|
989
|
+
protocolHandler,
|
|
990
|
+
},
|
|
991
|
+
);
|
|
693
992
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
993
|
+
const instantiateVow = watch(
|
|
994
|
+
instantiateInnerVow,
|
|
995
|
+
this.facets.rethrowUnlessMissingWatcher,
|
|
996
|
+
);
|
|
997
|
+
|
|
998
|
+
const attemptVow = watch(
|
|
999
|
+
instantiateVow,
|
|
1000
|
+
this.facets.binderOutboundInboundWatcher,
|
|
1001
|
+
{
|
|
1002
|
+
localAddr,
|
|
1003
|
+
remoteAddr,
|
|
1004
|
+
},
|
|
1005
|
+
);
|
|
1006
|
+
const acceptedVow = watch(
|
|
1007
|
+
attemptVow,
|
|
1008
|
+
this.facets.binderOutboundAcceptWatcher,
|
|
1009
|
+
{
|
|
1010
|
+
handler: lchandler,
|
|
1011
|
+
},
|
|
1012
|
+
);
|
|
1013
|
+
|
|
1014
|
+
return watch(acceptedVow, this.facets.binderOutboundCatchWatcher, {
|
|
1015
|
+
port,
|
|
1016
|
+
remoteAddr,
|
|
1017
|
+
lchandler,
|
|
1018
|
+
localAddr,
|
|
704
1019
|
});
|
|
705
|
-
|
|
706
|
-
|
|
1020
|
+
},
|
|
1021
|
+
async bind(localAddr) {
|
|
1022
|
+
return this.facets.binder.bind(localAddr);
|
|
1023
|
+
},
|
|
1024
|
+
},
|
|
1025
|
+
binder: {
|
|
1026
|
+
/** @param {string} localAddr */
|
|
1027
|
+
async bind(localAddr) {
|
|
1028
|
+
const { protocolHandler } = this.state;
|
|
1029
|
+
|
|
1030
|
+
// Check if we are underspecified (ends in slash)
|
|
1031
|
+
const underspecified = localAddr.endsWith(ENDPOINT_SEPARATOR);
|
|
1032
|
+
|
|
1033
|
+
const localAddrVow = watch(
|
|
1034
|
+
E(protocolHandler).generatePortID(localAddr, protocolHandler),
|
|
1035
|
+
this.facets.binderBindGeneratePortWatcher,
|
|
1036
|
+
{
|
|
1037
|
+
underspecified,
|
|
1038
|
+
localAddr,
|
|
1039
|
+
},
|
|
1040
|
+
);
|
|
1041
|
+
|
|
1042
|
+
return watch(localAddrVow, this.facets.binderBindWatcher);
|
|
1043
|
+
},
|
|
1044
|
+
},
|
|
1045
|
+
binderInboundInstantiateWatcher: {
|
|
1046
|
+
onFulfilled(localInstance, watchContext) {
|
|
1047
|
+
const { listenAddr, remoteAddr, port, listenPrefixIndex } =
|
|
1048
|
+
watchContext;
|
|
1049
|
+
const { listening, currentConnections } = this.state;
|
|
1050
|
+
const prefixes = getPrefixes(listenAddr);
|
|
1051
|
+
|
|
1052
|
+
const localAddr = localInstance
|
|
1053
|
+
? `${listenAddr}/${localInstance}`
|
|
1054
|
+
: listenAddr;
|
|
1055
|
+
const current = currentConnections.get(port);
|
|
1056
|
+
const inboundAttempt = makeInboundAttempt({
|
|
1057
|
+
localAddr,
|
|
1058
|
+
remoteAddr,
|
|
1059
|
+
currentConnections,
|
|
1060
|
+
listenPrefix: prefixes[listenPrefixIndex],
|
|
1061
|
+
listening,
|
|
1062
|
+
});
|
|
1063
|
+
|
|
1064
|
+
current.add(inboundAttempt);
|
|
1065
|
+
return inboundAttempt;
|
|
1066
|
+
},
|
|
1067
|
+
},
|
|
1068
|
+
binderInboundInstantiateCatchWatcher: {
|
|
1069
|
+
onRejected(e, watchContext) {
|
|
1070
|
+
let { lastFailure, listenPrefixIndex } = watchContext;
|
|
1071
|
+
|
|
1072
|
+
try {
|
|
1073
|
+
rethrowUnlessMissing(e);
|
|
1074
|
+
} catch (innerE) {
|
|
1075
|
+
lastFailure = innerE;
|
|
707
1076
|
}
|
|
708
1077
|
|
|
709
|
-
const {
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
1078
|
+
const { listenAddr, remoteAddr } = watchContext;
|
|
1079
|
+
|
|
1080
|
+
const { listening, protocolHandler } = this.state;
|
|
1081
|
+
|
|
1082
|
+
const prefixes = getPrefixes(listenAddr);
|
|
1083
|
+
|
|
1084
|
+
let listenPrefix;
|
|
1085
|
+
|
|
1086
|
+
listenPrefixIndex += 1;
|
|
1087
|
+
|
|
1088
|
+
while (listenPrefixIndex < prefixes.length) {
|
|
1089
|
+
listenPrefix = prefixes[listenPrefixIndex];
|
|
1090
|
+
if (!listening.has(listenPrefix)) {
|
|
1091
|
+
listenPrefixIndex += 1;
|
|
1092
|
+
continue;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
break;
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
if (listenPrefixIndex >= prefixes.length) {
|
|
1099
|
+
throw lastFailure;
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
const [port] = listening.get(/** @type {string} */ (listenPrefix));
|
|
1103
|
+
|
|
1104
|
+
const innerVow = watch(
|
|
1105
|
+
E(protocolHandler).onInstantiate(
|
|
1106
|
+
port,
|
|
1107
|
+
prefixes[listenPrefixIndex],
|
|
1108
|
+
remoteAddr,
|
|
1109
|
+
protocolHandler,
|
|
1110
|
+
),
|
|
1111
|
+
this.facets.binderInboundInstantiateWatcher,
|
|
1112
|
+
{
|
|
1113
|
+
listenAddr,
|
|
1114
|
+
remoteAddr,
|
|
1115
|
+
port,
|
|
1116
|
+
listenPrefixIndex,
|
|
1117
|
+
},
|
|
1118
|
+
);
|
|
1119
|
+
|
|
1120
|
+
return watch(
|
|
1121
|
+
innerVow,
|
|
1122
|
+
this.facets.binderInboundInstantiateCatchWatcher,
|
|
1123
|
+
{
|
|
1124
|
+
...watchContext,
|
|
1125
|
+
lastFailure,
|
|
1126
|
+
listenPrefixIndex,
|
|
1127
|
+
},
|
|
1128
|
+
);
|
|
1129
|
+
},
|
|
1130
|
+
},
|
|
1131
|
+
binderOutboundInstantiateWatcher: {
|
|
1132
|
+
onFulfilled(localInstance, watchContext) {
|
|
1133
|
+
const { localAddr } = watchContext;
|
|
1134
|
+
|
|
1135
|
+
return localInstance ? `${localAddr}/${localInstance}` : localAddr;
|
|
1136
|
+
},
|
|
1137
|
+
},
|
|
1138
|
+
binderOutboundConnectWatcher: {
|
|
1139
|
+
onFulfilled({ handler: rchandler }, watchContext) {
|
|
1140
|
+
const { lastFailure, remoteAddr, localAddr, lchandler, port } =
|
|
1141
|
+
watchContext;
|
|
1142
|
+
|
|
1143
|
+
const { currentConnections } = this.state;
|
|
726
1144
|
|
|
727
1145
|
if (!rchandler) {
|
|
728
1146
|
throw lastFailure;
|
|
729
1147
|
}
|
|
730
1148
|
|
|
731
1149
|
const current = currentConnections.get(port);
|
|
1150
|
+
|
|
732
1151
|
return crossoverConnection(
|
|
733
1152
|
zone,
|
|
734
1153
|
lchandler,
|
|
735
|
-
|
|
1154
|
+
localAddr,
|
|
736
1155
|
rchandler,
|
|
737
|
-
|
|
1156
|
+
remoteAddr,
|
|
738
1157
|
makeConnection,
|
|
739
1158
|
current,
|
|
740
1159
|
)[0];
|
|
741
1160
|
},
|
|
742
|
-
|
|
743
|
-
|
|
1161
|
+
},
|
|
1162
|
+
binderOutboundCatchWatcher: {
|
|
1163
|
+
onRejected(e, watchContext) {
|
|
1164
|
+
let lastFailure;
|
|
1165
|
+
|
|
1166
|
+
try {
|
|
1167
|
+
rethrowUnlessMissing(e);
|
|
1168
|
+
} catch (innerE) {
|
|
1169
|
+
lastFailure = innerE;
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
const { port, remoteAddr, lchandler, localAddr } = watchContext;
|
|
1173
|
+
|
|
1174
|
+
const { protocolHandler } = this.state;
|
|
1175
|
+
|
|
1176
|
+
const connectVow = watch(
|
|
1177
|
+
E(protocolHandler).onConnect(
|
|
1178
|
+
port,
|
|
1179
|
+
localAddr,
|
|
1180
|
+
remoteAddr,
|
|
1181
|
+
lchandler,
|
|
1182
|
+
protocolHandler,
|
|
1183
|
+
),
|
|
1184
|
+
);
|
|
1185
|
+
|
|
1186
|
+
return watch(connectVow, this.facets.binderOutboundConnectWatcher, {
|
|
1187
|
+
lastFailure,
|
|
1188
|
+
remoteAddr,
|
|
1189
|
+
localAddr,
|
|
1190
|
+
lchandler,
|
|
1191
|
+
port,
|
|
1192
|
+
});
|
|
744
1193
|
},
|
|
745
1194
|
},
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
1195
|
+
binderOutboundInboundWatcher: {
|
|
1196
|
+
onFulfilled(initialLocalAddress, watchContext) {
|
|
1197
|
+
const { remoteAddr, localAddr } = watchContext;
|
|
1198
|
+
|
|
1199
|
+
if (initialLocalAddress === undefined) {
|
|
1200
|
+
initialLocalAddress = localAddr;
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
// Attempt the loopback connection.
|
|
1204
|
+
return this.facets.protocolImpl.inbound(
|
|
1205
|
+
remoteAddr,
|
|
1206
|
+
initialLocalAddress,
|
|
1207
|
+
);
|
|
1208
|
+
},
|
|
1209
|
+
},
|
|
1210
|
+
binderOutboundAcceptWatcher: {
|
|
1211
|
+
onFulfilled(attempt, watchContext) {
|
|
1212
|
+
const { handler } = watchContext;
|
|
1213
|
+
return attempt.accept({ handler });
|
|
1214
|
+
},
|
|
1215
|
+
},
|
|
1216
|
+
binderBindGeneratePortWatcher: {
|
|
1217
|
+
onFulfilled(portID, watchContext) {
|
|
1218
|
+
const { localAddr, underspecified } = watchContext;
|
|
1219
|
+
const { protocolHandler, boundPorts } = this.state;
|
|
1220
|
+
|
|
1221
|
+
if (!underspecified) {
|
|
1222
|
+
return localAddr;
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
const newAddr = `${localAddr}${portID}`;
|
|
1226
|
+
if (!boundPorts.has(newAddr)) {
|
|
1227
|
+
return newAddr;
|
|
1228
|
+
}
|
|
1229
|
+
return watch(
|
|
1230
|
+
E(protocolHandler).generatePortID(localAddr, protocolHandler),
|
|
1231
|
+
this.facets.binderBindGeneratePortWatcher,
|
|
1232
|
+
watchContext,
|
|
1233
|
+
);
|
|
1234
|
+
},
|
|
1235
|
+
},
|
|
1236
|
+
binderPortWatcher: {
|
|
1237
|
+
onFulfilled(_value, watchContext) {
|
|
1238
|
+
const { port, localAddr } = watchContext;
|
|
1239
|
+
const { boundPorts, currentConnections } = this.state;
|
|
1240
|
+
|
|
1241
|
+
boundPorts.init(localAddr, harden(port));
|
|
1242
|
+
currentConnections.init(
|
|
1243
|
+
port,
|
|
1244
|
+
zone.detached().setStore('connections'),
|
|
1245
|
+
);
|
|
1246
|
+
return port;
|
|
1247
|
+
},
|
|
1248
|
+
},
|
|
1249
|
+
binderBindWatcher: {
|
|
1250
|
+
onFulfilled(localAddr) {
|
|
749
1251
|
const {
|
|
750
|
-
protocolHandler,
|
|
751
1252
|
boundPorts,
|
|
752
1253
|
listening,
|
|
753
1254
|
openConnections,
|
|
754
1255
|
currentConnections,
|
|
1256
|
+
protocolHandler,
|
|
755
1257
|
} = this.state;
|
|
756
1258
|
|
|
757
|
-
// Check if we are underspecified (ends in slash)
|
|
758
|
-
const underspecified = localAddr.endsWith(ENDPOINT_SEPARATOR);
|
|
759
|
-
for await (const _ of whileTrue(() => underspecified)) {
|
|
760
|
-
const portID = await when(
|
|
761
|
-
E(protocolHandler).generatePortID(localAddr, protocolHandler),
|
|
762
|
-
);
|
|
763
|
-
const newAddr = `${localAddr}${portID}`;
|
|
764
|
-
if (!boundPorts.has(newAddr)) {
|
|
765
|
-
localAddr = newAddr;
|
|
766
|
-
break;
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
|
|
770
|
-
this.state.localAddr = localAddr;
|
|
771
|
-
|
|
772
1259
|
if (boundPorts.has(localAddr)) {
|
|
773
1260
|
return boundPorts.get(localAddr);
|
|
774
1261
|
}
|
|
@@ -783,17 +1270,38 @@ const prepareBinder = (zone, powers) => {
|
|
|
783
1270
|
protocolImpl: this.facets.protocolImpl,
|
|
784
1271
|
});
|
|
785
1272
|
|
|
786
|
-
|
|
1273
|
+
return watch(
|
|
787
1274
|
E(protocolHandler).onBind(port, localAddr, protocolHandler),
|
|
1275
|
+
this.facets.binderPortWatcher,
|
|
1276
|
+
{
|
|
1277
|
+
port,
|
|
1278
|
+
localAddr,
|
|
1279
|
+
},
|
|
788
1280
|
);
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
1281
|
+
},
|
|
1282
|
+
},
|
|
1283
|
+
rethrowUnlessMissingWatcher: {
|
|
1284
|
+
onRejected(e) {
|
|
1285
|
+
rethrowUnlessMissing(e);
|
|
792
1286
|
},
|
|
793
1287
|
},
|
|
794
1288
|
},
|
|
795
1289
|
);
|
|
796
1290
|
|
|
1291
|
+
const makeBinderKit = ({
|
|
1292
|
+
currentConnections,
|
|
1293
|
+
boundPorts,
|
|
1294
|
+
listening,
|
|
1295
|
+
protocolHandler,
|
|
1296
|
+
}) => {
|
|
1297
|
+
const { protocolImpl, binder } = makeFullBinderKit({
|
|
1298
|
+
currentConnections,
|
|
1299
|
+
boundPorts,
|
|
1300
|
+
listening,
|
|
1301
|
+
protocolHandler,
|
|
1302
|
+
});
|
|
1303
|
+
return harden({ protocolImpl, binder });
|
|
1304
|
+
};
|
|
797
1305
|
return makeBinderKit;
|
|
798
1306
|
};
|
|
799
1307
|
|
|
@@ -925,10 +1433,10 @@ export const prepareEchoConnectionKit = zone => {
|
|
|
925
1433
|
* @param {import('@agoric/base-zone').Zone} zone
|
|
926
1434
|
* @param {ReturnType<import('@agoric/vow').prepareVowTools>} powers
|
|
927
1435
|
*/
|
|
928
|
-
export function prepareLoopbackProtocolHandler(zone, {
|
|
1436
|
+
export function prepareLoopbackProtocolHandler(zone, { watch }) {
|
|
929
1437
|
const detached = zone.detached();
|
|
930
1438
|
|
|
931
|
-
const
|
|
1439
|
+
const makeLoopbackProtocolHandlerKit = zone.exoClassKit(
|
|
932
1440
|
'ProtocolHandler',
|
|
933
1441
|
Shape.ProtocolHandlerI,
|
|
934
1442
|
/** @param {string} [instancePrefix] */
|
|
@@ -944,80 +1452,118 @@ export function prepareLoopbackProtocolHandler(zone, { when }) {
|
|
|
944
1452
|
};
|
|
945
1453
|
},
|
|
946
1454
|
{
|
|
947
|
-
|
|
948
|
-
|
|
1455
|
+
protocolHandler: {
|
|
1456
|
+
async onCreate(_impl, _protocolHandler) {
|
|
1457
|
+
// noop
|
|
1458
|
+
},
|
|
1459
|
+
async generatePortID(_localAddr, _protocolHandler) {
|
|
1460
|
+
this.state.portNonce += 1n;
|
|
1461
|
+
return `port${this.state.portNonce}`;
|
|
1462
|
+
},
|
|
1463
|
+
async onBind(_port, _localAddr, _protocolHandler) {
|
|
1464
|
+
// noop, for now; Maybe handle a bind?
|
|
1465
|
+
},
|
|
1466
|
+
async onConnect(
|
|
1467
|
+
_port,
|
|
1468
|
+
localAddr,
|
|
1469
|
+
remoteAddr,
|
|
1470
|
+
_chandler,
|
|
1471
|
+
protocolHandler,
|
|
1472
|
+
) {
|
|
1473
|
+
const { listeners } = this.state;
|
|
1474
|
+
const [lport, lhandler] = listeners.get(remoteAddr);
|
|
1475
|
+
|
|
1476
|
+
const acceptVow = watch(
|
|
1477
|
+
E(lhandler).onAccept(lport, remoteAddr, localAddr, lhandler),
|
|
1478
|
+
this.facets.protocolHandlerAcceptWatcher,
|
|
1479
|
+
);
|
|
1480
|
+
|
|
1481
|
+
const instantiateInnerVow = watch(
|
|
1482
|
+
E(protocolHandler).onInstantiate(
|
|
1483
|
+
lport,
|
|
1484
|
+
remoteAddr,
|
|
1485
|
+
localAddr,
|
|
1486
|
+
protocolHandler,
|
|
1487
|
+
),
|
|
1488
|
+
this.facets.protocolHandlerInstantiateWatcher,
|
|
1489
|
+
);
|
|
1490
|
+
|
|
1491
|
+
const instantiateVow = watch(
|
|
1492
|
+
instantiateInnerVow,
|
|
1493
|
+
this.facets.rethrowUnlessMissingWatcher,
|
|
1494
|
+
);
|
|
1495
|
+
return watch(
|
|
1496
|
+
Promise.all([acceptVow, instantiateVow]),
|
|
1497
|
+
this.facets.protocolHandlerConnectWatcher,
|
|
1498
|
+
);
|
|
1499
|
+
},
|
|
1500
|
+
async onInstantiate(_port, _localAddr, _remote, _protocol) {
|
|
1501
|
+
const { instancePrefix } = this.state;
|
|
1502
|
+
this.state.instanceNonce += 1n;
|
|
1503
|
+
return `${instancePrefix}${this.state.instanceNonce}`;
|
|
1504
|
+
},
|
|
1505
|
+
async onListen(port, localAddr, listenHandler, _protocolHandler) {
|
|
1506
|
+
const { listeners } = this.state;
|
|
1507
|
+
|
|
1508
|
+
// This implementation has a simple last-one-wins replacement policy.
|
|
1509
|
+
// Other handlers might use different policies.
|
|
1510
|
+
if (listeners.has(localAddr)) {
|
|
1511
|
+
const lhandler = listeners.get(localAddr)[1];
|
|
1512
|
+
if (lhandler !== listenHandler) {
|
|
1513
|
+
listeners.set(localAddr, [port, listenHandler]);
|
|
1514
|
+
}
|
|
1515
|
+
} else {
|
|
1516
|
+
listeners.init(localAddr, harden([port, listenHandler]));
|
|
1517
|
+
}
|
|
1518
|
+
},
|
|
1519
|
+
/**
|
|
1520
|
+
* @param {Port} port
|
|
1521
|
+
* @param {Endpoint} localAddr
|
|
1522
|
+
* @param {ListenHandler} listenHandler
|
|
1523
|
+
* @param {*} _protocolHandler
|
|
1524
|
+
*/
|
|
1525
|
+
async onListenRemove(port, localAddr, listenHandler, _protocolHandler) {
|
|
1526
|
+
const { listeners } = this.state;
|
|
1527
|
+
const [lport, lhandler] = listeners.get(localAddr);
|
|
1528
|
+
lport === port || Fail`Port does not match listener on ${localAddr}`;
|
|
1529
|
+
lhandler === listenHandler ||
|
|
1530
|
+
Fail`Listen handler does not match listener on ${localAddr}`;
|
|
1531
|
+
listeners.delete(localAddr);
|
|
1532
|
+
},
|
|
1533
|
+
async onRevoke(_port, _localAddr, _protocolHandler) {
|
|
1534
|
+
// This is an opportunity to clean up resources.
|
|
1535
|
+
},
|
|
1536
|
+
},
|
|
1537
|
+
protocolHandlerAcceptWatcher: {
|
|
1538
|
+
onFulfilled(rchandler) {
|
|
1539
|
+
return rchandler;
|
|
1540
|
+
},
|
|
949
1541
|
},
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
1542
|
+
protocolHandlerConnectWatcher: {
|
|
1543
|
+
onFulfilled(results) {
|
|
1544
|
+
return {
|
|
1545
|
+
remoteInstance: results[0],
|
|
1546
|
+
handler: results[1],
|
|
1547
|
+
};
|
|
1548
|
+
},
|
|
953
1549
|
},
|
|
954
|
-
|
|
955
|
-
|
|
1550
|
+
protocolHandlerInstantiateWatcher: {
|
|
1551
|
+
onFulfilled(remoteInstance) {
|
|
1552
|
+
return remoteInstance;
|
|
1553
|
+
},
|
|
956
1554
|
},
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
_chandler,
|
|
962
|
-
protocolHandler,
|
|
963
|
-
) {
|
|
964
|
-
const { listeners } = this.state;
|
|
965
|
-
const [lport, lhandler] = listeners.get(remoteAddr);
|
|
966
|
-
const rchandler = await when(
|
|
967
|
-
E(lhandler).onAccept(lport, remoteAddr, localAddr, lhandler),
|
|
968
|
-
);
|
|
969
|
-
// console.log(`rchandler is`, rchandler);
|
|
970
|
-
const remoteInstance = await when(
|
|
971
|
-
E(protocolHandler).onInstantiate(
|
|
972
|
-
lport,
|
|
973
|
-
remoteAddr,
|
|
974
|
-
localAddr,
|
|
975
|
-
protocolHandler,
|
|
976
|
-
),
|
|
977
|
-
).catch(rethrowUnlessMissing);
|
|
978
|
-
return {
|
|
979
|
-
remoteInstance,
|
|
980
|
-
handler: rchandler,
|
|
981
|
-
};
|
|
982
|
-
},
|
|
983
|
-
async onInstantiate(_port, _localAddr, _remote, _protocol) {
|
|
984
|
-
const { instancePrefix } = this.state;
|
|
985
|
-
this.state.instanceNonce += 1n;
|
|
986
|
-
return `${instancePrefix}${this.state.instanceNonce}`;
|
|
987
|
-
},
|
|
988
|
-
async onListen(port, localAddr, listenHandler, _protocolHandler) {
|
|
989
|
-
const { listeners } = this.state;
|
|
990
|
-
|
|
991
|
-
// This implementation has a simple last-one-wins replacement policy.
|
|
992
|
-
// Other handlers might use different policies.
|
|
993
|
-
if (listeners.has(localAddr)) {
|
|
994
|
-
const lhandler = listeners.get(localAddr)[1];
|
|
995
|
-
if (lhandler !== listenHandler) {
|
|
996
|
-
listeners.set(localAddr, [port, listenHandler]);
|
|
997
|
-
}
|
|
998
|
-
} else {
|
|
999
|
-
listeners.init(localAddr, harden([port, listenHandler]));
|
|
1000
|
-
}
|
|
1001
|
-
},
|
|
1002
|
-
/**
|
|
1003
|
-
* @param {Port} port
|
|
1004
|
-
* @param {Endpoint} localAddr
|
|
1005
|
-
* @param {ListenHandler} listenHandler
|
|
1006
|
-
* @param {*} _protocolHandler
|
|
1007
|
-
*/
|
|
1008
|
-
async onListenRemove(port, localAddr, listenHandler, _protocolHandler) {
|
|
1009
|
-
const { listeners } = this.state;
|
|
1010
|
-
const [lport, lhandler] = listeners.get(localAddr);
|
|
1011
|
-
lport === port || Fail`Port does not match listener on ${localAddr}`;
|
|
1012
|
-
lhandler === listenHandler ||
|
|
1013
|
-
Fail`Listen handler does not match listener on ${localAddr}`;
|
|
1014
|
-
listeners.delete(localAddr);
|
|
1015
|
-
},
|
|
1016
|
-
async onRevoke(_port, _localAddr, _protocolHandler) {
|
|
1017
|
-
// This is an opportunity to clean up resources.
|
|
1555
|
+
rethrowUnlessMissingWatcher: {
|
|
1556
|
+
onRejected(e) {
|
|
1557
|
+
rethrowUnlessMissing(e);
|
|
1558
|
+
},
|
|
1018
1559
|
},
|
|
1019
1560
|
},
|
|
1020
1561
|
);
|
|
1021
1562
|
|
|
1563
|
+
const makeLoopbackProtocolHandler = instancePrefix => {
|
|
1564
|
+
const { protocolHandler } = makeLoopbackProtocolHandlerKit(instancePrefix);
|
|
1565
|
+
return harden(protocolHandler);
|
|
1566
|
+
};
|
|
1567
|
+
|
|
1022
1568
|
return makeLoopbackProtocolHandler;
|
|
1023
1569
|
}
|