@dxos/network-manager 0.1.48 → 0.1.49-next.7ec9d52

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.
@@ -1 +1 @@
1
- {"version":3,"file":"network-manager.d.ts","sourceRoot":"","sources":["../../../src/network-manager.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAa,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE3D,OAAO,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAC;AAG7E,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEvD;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB,CAAC;AAGF,MAAM,MAAM,YAAY,GAAG;IACzB;;OAEG;IACH,KAAK,EAAE,SAAS,CAAC;IAEjB;;OAEG;IACH,MAAM,EAAE,SAAS,CAAC;IAElB;;OAEG;IACH,gBAAgB,EAAE,oBAAoB,CAAC;IAEvC;;OAEG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAEpB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,aAAa,EAAE,aAAa,CAAC;IAC7B,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,CAAC;AAEF;;GAEG;AAEH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoD;IAC5E,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0D;IAEnF,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAmB;IACrD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAgB;IAC/C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAY;IACvC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAmB;IAErD,OAAO,CAAC,gBAAgB,CAA0B;IAClD,SAAgB,sBAAsB,yBAAgC;IAEtE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAgB;IAEhD,SAAgB,aAAa,cAAqB;IAElD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA8B;gBAE9C,EAAE,gBAAgB,EAAE,aAAa,EAAE,GAAG,EAAE,EAAE,qBAAqB;IAmB3E,IAAI,aAAa,8BAEhB;IAED,IAAI,eAAe,oBAElB;IAGD,IAAI,MAAM,gBAET;IAED,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS;IAItD,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,KAAK,GAAG,SAAS;IAIvC,IAAI;IAOJ,KAAK;IAWX;;OAEG;IACG,SAAS,CAAC,EACd,KAAK,EACL,MAAM,EACN,QAAQ,EACR,gBAAgB,EAAE,QAAQ,EAC1B,KAAK,GACN,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC;IA4B1C;;OAEG;IACG,UAAU,CAAC,KAAK,EAAE,SAAS;IAuB3B,kBAAkB,CAAC,KAAK,EAAE,eAAe;CA0BhD"}
1
+ {"version":3,"file":"network-manager.d.ts","sourceRoot":"","sources":["../../../src/network-manager.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAa,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE3D,OAAO,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAC;AAG7E,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEvD;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB,CAAC;AAGF,MAAM,MAAM,YAAY,GAAG;IACzB;;OAEG;IACH,KAAK,EAAE,SAAS,CAAC;IAEjB;;OAEG;IACH,MAAM,EAAE,SAAS,CAAC;IAElB;;OAEG;IACH,gBAAgB,EAAE,oBAAoB,CAAC;IAEvC;;OAEG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAEpB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,aAAa,EAAE,aAAa,CAAC;IAC7B,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,CAAC;AAEF;;GAEG;AAEH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoD;IAC5E,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0D;IAEnF,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAmB;IACrD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAgB;IAC/C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAY;IACvC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAmB;IAErD,OAAO,CAAC,gBAAgB,CAA0B;IAClD,SAAgB,sBAAsB,yBAAgC;IAEtE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAgB;IAEhD,SAAgB,aAAa,cAAqB;IAElD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA8B;gBAE9C,EAAE,gBAAgB,EAAE,aAAa,EAAE,GAAG,EAAE,EAAE,qBAAqB;IAmB3E,IAAI,aAAa,8BAEhB;IAED,IAAI,eAAe,oBAElB;IAGD,IAAI,MAAM,gBAET;IAED,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS;IAItD,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,KAAK,GAAG,SAAS;IAIvC,IAAI;IAOJ,KAAK;IAWX;;OAEG;IACG,SAAS,CAAC,EACd,KAAK,EACL,MAAM,EACN,QAAQ,EACR,gBAAgB,EAAE,QAAQ,EAC1B,KAAK,GACN,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC;IAgC1C;;OAEG;IACG,UAAU,CAAC,KAAK,EAAE,SAAS;IAuB3B,kBAAkB,CAAC,KAAK,EAAE,eAAe;CA0BhD"}
@@ -1,5 +1,5 @@
1
1
  import { PublicKey } from '@dxos/keys';
2
- import { Answer, Offer, Signal } from '@dxos/protocols/proto/dxos/mesh/swarm';
2
+ import { Answer, Offer, Signal, SignalBatch } from '@dxos/protocols/proto/dxos/mesh/swarm';
3
3
  export interface OfferMessage {
4
4
  author: PublicKey;
5
5
  recipient: PublicKey;
@@ -15,7 +15,8 @@ export interface SignalMessage {
15
15
  topic: PublicKey;
16
16
  sessionId: PublicKey;
17
17
  data: {
18
- signal: Signal;
18
+ signal?: Signal;
19
+ signalBatch?: SignalBatch;
19
20
  };
20
21
  }
21
22
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"signal-messenger.d.ts","sourceRoot":"","sources":["../../../../src/signal/signal-messenger.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,uCAAuC,CAAC;AAE9E,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,SAAS,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,KAAK,EAAE,SAAS,CAAC;IACjB,SAAS,EAAE,SAAS,CAAC;IACrB,IAAI,EAAE;QAAE,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,SAAS,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,KAAK,EAAE,SAAS,CAAC;IACjB,SAAS,EAAE,SAAS,CAAC;IACrB,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE1C;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C"}
1
+ {"version":3,"file":"signal-messenger.d.ts","sourceRoot":"","sources":["../../../../src/signal/signal-messenger.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AAE3F,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,SAAS,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,KAAK,EAAE,SAAS,CAAC;IACjB,SAAS,EAAE,SAAS,CAAC;IACrB,IAAI,EAAE;QAAE,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,SAAS,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,KAAK,EAAE,SAAS,CAAC;IACjB,SAAS,EAAE,SAAS,CAAC;IACrB,IAAI,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,WAAW,CAAA;KAAE,CAAC;CACtD;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE1C;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C"}
@@ -1 +1 @@
1
- {"version":3,"file":"swarm-messenger.d.ts","sourceRoot":"","sources":["../../../../src/signal/swarm-messenger.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAC;AAE3C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,MAAM,EAAgB,MAAM,uCAAuC,CAAC;AAG7E,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAMlF,MAAM,MAAM,qBAAqB,GAAG;IAClC,WAAW,EAAE,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,SAAS,CAAC;QAAC,SAAS,EAAE,SAAS,CAAC;QAAC,OAAO,EAAE,GAAG,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClG,OAAO,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,QAAQ,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,KAAK,EAAE,SAAS,CAAC;CAClB,CAAC;AAEF;;GAEG;AACH,qBAAa,cAAe,YAAW,eAAe;IACpD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiB;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4C;IACtE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAoF;IAEjH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6C;IACtE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IAEnC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA4E;gBAE9F,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,qBAAqB;IAOtE,cAAc,CAAC,EACnB,MAAM,EACN,SAAS,EACT,OAAO,GACR,EAAE;QACD,MAAM,EAAE,SAAS,CAAC;QAClB,SAAS,EAAE,SAAS,CAAC;QACrB,OAAO,EAAE,GAAG,CAAC;KACd,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBX,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAS7C,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;YAerC,oBAAoB;YA0BpB,eAAe;YAWf,YAAY;YA6BZ,aAAa;CAoB5B"}
1
+ {"version":3,"file":"swarm-messenger.d.ts","sourceRoot":"","sources":["../../../../src/signal/swarm-messenger.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAC;AAE3C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,MAAM,EAAgB,MAAM,uCAAuC,CAAC;AAG7E,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAMlF,MAAM,MAAM,qBAAqB,GAAG;IAClC,WAAW,EAAE,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,SAAS,CAAC;QAAC,SAAS,EAAE,SAAS,CAAC;QAAC,OAAO,EAAE,GAAG,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClG,OAAO,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,QAAQ,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,KAAK,EAAE,SAAS,CAAC;CAClB,CAAC;AAEF;;GAEG;AACH,qBAAa,cAAe,YAAW,eAAe;IACpD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiB;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4C;IACtE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAoF;IAEjH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6C;IACtE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IAEnC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA4E;gBAE9F,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,qBAAqB;IAOtE,cAAc,CAAC,EACnB,MAAM,EACN,SAAS,EACT,OAAO,GACR,EAAE;QACD,MAAM,EAAE,SAAS,CAAC;QAClB,SAAS,EAAE,SAAS,CAAC;QACrB,OAAO,EAAE,GAAG,CAAC;KACd,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BX,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAS7C,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;YAerC,oBAAoB;YA0BpB,eAAe;YAWf,YAAY;YAiCZ,aAAa;CAuB5B"}
@@ -43,12 +43,16 @@ export declare class Connection {
43
43
  private readonly _signalMessaging;
44
44
  private readonly _protocol;
45
45
  private readonly _transportFactory;
46
+ private readonly _ctx;
46
47
  private _state;
47
48
  private _transport;
48
- private _bufferedSignals;
49
+ private _incomingSignalBuffer;
50
+ private _outgoingSignalBuffer;
49
51
  readonly stateChanged: Event<ConnectionState>;
50
52
  readonly errors: ErrorStream;
51
53
  _instanceId: string;
54
+ private readonly _signalSendTask;
55
+ private _signallingDelay;
52
56
  constructor(topic: PublicKey, ownId: PublicKey, // TODO(burdon): peerID?
53
57
  remoteId: PublicKey, sessionId: PublicKey, initiator: boolean, _signalMessaging: SignalMessenger, _protocol: WireProtocol, _transportFactory: TransportFactory);
54
58
  get state(): ConnectionState;
@@ -59,6 +63,11 @@ export declare class Connection {
59
63
  */
60
64
  openConnection(): void;
61
65
  close(): Promise<void>;
66
+ private _sendSignal;
67
+ private _flushSignalBuffer;
68
+ /**
69
+ * Receive a signal from the remote peer.
70
+ */
62
71
  signal(msg: SignalMessage): Promise<void>;
63
72
  private _changeState;
64
73
  }
@@ -1 +1 @@
1
- {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../../../src/swarm/connection.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,EAAgB,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAKvC,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhD;;GAEG;AACH,oBAAY,eAAe;IACzB;;;OAGG;IACH,OAAO,YAAY;IAEnB;;OAEG;IACH,UAAU,eAAe;IAEzB;;OAEG;IACH,SAAS,cAAc;IAEvB;;OAEG;IACH,OAAO,YAAY;IAEnB;;OAEG;IACH,MAAM,WAAW;CAClB;AAED;;;GAGG;AACH,qBAAa,UAAU;aAWH,KAAK,EAAE,SAAS;aAChB,KAAK,EAAE,SAAS;aAChB,QAAQ,EAAE,SAAS;aACnB,SAAS,EAAE,SAAS;aACpB,SAAS,EAAE,OAAO;IAClC,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAjBpC,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,UAAU,CAAwB;IAC1C,OAAO,CAAC,gBAAgB,CAAgB;IAExC,QAAQ,CAAC,YAAY,yBAAgC;IACrD,QAAQ,CAAC,MAAM,cAAqB;IAE7B,WAAW,SAA8B;gBAG9B,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,SAAS,EAAE,wBAAwB;IAC1C,QAAQ,EAAE,SAAS,EACnB,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,OAAO,EACjB,gBAAgB,EAAE,eAAe,EACjC,SAAS,EAAE,YAAY,EACvB,iBAAiB,EAAE,gBAAgB;IAGtD,IAAI,KAAK,oBAER;IAED,IAAI,SAAS,0BAEZ;IAED,IAAI,QAAQ,iBAEX;IAED;;OAEG;IAEH,cAAc;IAgER,KAAK;IA0BL,MAAM,CAAC,GAAG,EAAE,aAAa;IAqB/B,OAAO,CAAC,YAAY;CAMrB"}
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../../../src/swarm/connection.ts"],"names":[],"mappings":"AAMA,OAAO,EAAgB,KAAK,EAAuB,MAAM,aAAa,CAAC;AAEvE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAKvC,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAahD;;GAEG;AACH,oBAAY,eAAe;IACzB;;;OAGG;IACH,OAAO,YAAY;IAEnB;;OAEG;IACH,UAAU,eAAe;IAEzB;;OAEG;IACH,SAAS,cAAc;IAEvB;;OAEG;IACH,OAAO,YAAY;IAEnB;;OAEG;IACH,MAAM,WAAW;CAClB;AAED;;;GAGG;AACH,qBAAa,UAAU;aAqBH,KAAK,EAAE,SAAS;aAChB,KAAK,EAAE,SAAS;aAChB,QAAQ,EAAE,SAAS;aACnB,SAAS,EAAE,SAAS;aACpB,SAAS,EAAE,OAAO;IAClC,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IA3BpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiB;IAEtC,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,UAAU,CAAwB;IAE1C,OAAO,CAAC,qBAAqB,CAAgB;IAC7C,OAAO,CAAC,qBAAqB,CAAgB;IAE7C,QAAQ,CAAC,YAAY,yBAAgC;IACrD,QAAQ,CAAC,MAAM,cAAqB;IAE7B,WAAW,SAA8B;IAEhD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAE7B;IAEH,OAAO,CAAC,gBAAgB,CAA6B;gBAGnC,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,SAAS,EAAE,wBAAwB;IAC1C,QAAQ,EAAE,SAAS,EACnB,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,OAAO,EACjB,gBAAgB,EAAE,eAAe,EACjC,SAAS,EAAE,YAAY,EACvB,iBAAiB,EAAE,gBAAgB;IAGtD,IAAI,KAAK,oBAER;IAED,IAAI,SAAS,0BAEZ;IAED,IAAI,QAAQ,iBAEX;IAED;;OAEG;IAEH,cAAc;IAkDR,KAAK;IA4BX,OAAO,CAAC,WAAW;YAKL,kBAAkB;IA8BhC;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,aAAa;IA2B/B,OAAO,CAAC,YAAY;CAMrB"}
@@ -24,6 +24,7 @@ export declare class Swarm {
24
24
  private readonly _label;
25
25
  private readonly _swarmMessenger;
26
26
  private _ctx;
27
+ private _listeningHandle?;
27
28
  /**
28
29
  * Unique id of the swarm, local to the current peer, generated when swarm is joined.
29
30
  */
@@ -37,6 +38,7 @@ export declare class Swarm {
37
38
  */
38
39
  get label(): string | undefined;
39
40
  get topic(): Topic;
41
+ open(): Promise<void>;
40
42
  destroy(): Promise<void>;
41
43
  setTopology(topology: Topology): Promise<void>;
42
44
  onSwarmEvent(swarmEvent: SwarmEvent): void;
@@ -1 +1 @@
1
- {"version":3,"file":"swarm.d.ts","sourceRoot":"","sources":["../../../../src/swarm/swarm.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,uCAAuC,CAAC;AAG/D,OAAO,EAAkB,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACxE,OAAO,EAAmB,QAAQ,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAmB,MAAM,cAAc,CAAC;AAQ3D;;;;GAIG;AACH,qBAAa,KAAK;IAwCd,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAxCzB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAiB;IAEjD,OAAO,CAAC,IAAI,CAAiB;IAE7B;;OAEG;IAEH,QAAQ,CAAC,WAAW,SAA8B;IAoBlD,QAAQ,CAAC,MAAM,cAAqB;gBAMjB,MAAM,EAAE,SAAS,EACjB,UAAU,EAAE,SAAS,EAC9B,SAAS,EAAE,QAAQ,EACV,iBAAiB,EAAE,oBAAoB,EACvC,UAAU,EAAE,SAAS,EACrB,iBAAiB,EAAE,gBAAgB,EACnC,MAAM,EAAE,MAAM,GAAG,SAAS;IA+B7C,IAAI,WAAW,iBAId;IAED,IACI,SAAS,cAEZ;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,MAAM,GAAG,SAAS,CAE9B;IAED,IACI,KAAK,IAAI,KAAK,CAEjB;IAGK,OAAO;IAQP,WAAW,CAAC,QAAQ,EAAE,QAAQ;IAiBpC,YAAY,CAAC,UAAU,EAAE,UAAU;IA8B7B,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAyB/C,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB/C,SAAS;IAOT,QAAQ;IAId,OAAO,CAAC,gBAAgB;YAiDV,YAAY;IAM1B,OAAO,CAAC,mBAAmB;IAuC3B;;OAEG;YACW,mBAAmB;YA0BnB,gBAAgB;CAQ/B"}
1
+ {"version":3,"file":"swarm.d.ts","sourceRoot":"","sources":["../../../../src/swarm/swarm.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAmB,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE7D,OAAO,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,uCAAuC,CAAC;AAG/D,OAAO,EAAkB,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACxE,OAAO,EAAmB,QAAQ,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAmB,MAAM,cAAc,CAAC;AAQ3D;;;;GAIG;AACH,qBAAa,KAAK;IA0Cd,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM;IA1CzB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAiB;IAEjD,OAAO,CAAC,IAAI,CAAiB;IAE7B,OAAO,CAAC,gBAAgB,CAAC,CAA8B;IAEvD;;OAEG;IAEH,QAAQ,CAAC,WAAW,SAA8B;IAoBlD,QAAQ,CAAC,MAAM,cAAqB;gBAMjB,MAAM,EAAE,SAAS,EACjB,UAAU,EAAE,SAAS,EAC9B,SAAS,EAAE,QAAQ,EACV,iBAAiB,EAAE,oBAAoB,EACvC,UAAU,EAAE,SAAS,EACrB,iBAAiB,EAAE,gBAAgB,EACnC,MAAM,EAAE,MAAM,GAAG,SAAS;IAkB7C,IAAI,WAAW,iBAId;IAED,IACI,SAAS,cAEZ;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,MAAM,GAAG,SAAS,CAE9B;IAED,IACI,KAAK,IAAI,KAAK,CAEjB;IAEK,IAAI;IAaJ,OAAO;IAWP,WAAW,CAAC,QAAQ,EAAE,QAAQ;IAiBpC,YAAY,CAAC,UAAU,EAAE,UAAU;IA8B7B,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAyB/C,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB/C,SAAS;IAOT,QAAQ;IAId,OAAO,CAAC,gBAAgB;YAiDV,YAAY;IAM1B,OAAO,CAAC,mBAAmB;IAuC3B;;OAEG;YACW,mBAAmB;YA0BnB,gBAAgB;CAQ/B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/network-manager",
3
- "version": "0.1.48",
3
+ "version": "0.1.49-next.7ec9d52",
4
4
  "description": "Network Manager",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -22,23 +22,24 @@
22
22
  "@koush/wrtc": "^0.5.3",
23
23
  "isomorphic-ws": "^4.0.1",
24
24
  "nanomessage-rpc": "^3.0.0",
25
- "simple-peer": "9.11.0",
25
+ "simple-peer": "9.11.1",
26
26
  "ws": "^7.4.4",
27
27
  "xor-distance": "^2.0.0",
28
- "@dxos/async": "0.1.48",
29
- "@dxos/codec-protobuf": "0.1.48",
30
- "@dxos/context": "0.1.48",
31
- "@dxos/credentials": "0.1.48",
32
- "@dxos/crypto": "0.1.48",
33
- "@dxos/debug": "0.1.48",
34
- "@dxos/keys": "0.1.48",
35
- "@dxos/log": "0.1.48",
36
- "@dxos/messaging": "0.1.48",
37
- "@dxos/node-std": "0.1.48",
38
- "@dxos/protocols": "0.1.48",
39
- "@dxos/rpc": "0.1.48",
40
- "@dxos/teleport": "0.1.48",
41
- "@dxos/util": "0.1.48"
28
+ "@dxos/async": "0.1.49-next.7ec9d52",
29
+ "@dxos/codec-protobuf": "0.1.49-next.7ec9d52",
30
+ "@dxos/context": "0.1.49-next.7ec9d52",
31
+ "@dxos/credentials": "0.1.49-next.7ec9d52",
32
+ "@dxos/crypto": "0.1.49-next.7ec9d52",
33
+ "@dxos/debug": "0.1.49-next.7ec9d52",
34
+ "@dxos/errors": "0.1.49-next.7ec9d52",
35
+ "@dxos/keys": "0.1.49-next.7ec9d52",
36
+ "@dxos/log": "0.1.49-next.7ec9d52",
37
+ "@dxos/messaging": "0.1.49-next.7ec9d52",
38
+ "@dxos/node-std": "0.1.49-next.7ec9d52",
39
+ "@dxos/protocols": "0.1.49-next.7ec9d52",
40
+ "@dxos/rpc": "0.1.49-next.7ec9d52",
41
+ "@dxos/teleport": "0.1.49-next.7ec9d52",
42
+ "@dxos/util": "0.1.49-next.7ec9d52"
42
43
  },
43
44
  "devDependencies": {
44
45
  "@swc-node/register": "1.5.4",
@@ -48,7 +49,7 @@
48
49
  "earljs": "~0.1.10",
49
50
  "fast-check": "~3.3.0",
50
51
  "typescript": "^5.0.4",
51
- "@dxos/signal": "0.1.48"
52
+ "@dxos/signal": "0.1.49-next.7ec9d52"
52
53
  },
53
54
  "publishConfig": {
54
55
  "access": "public"
@@ -166,9 +166,13 @@ export class NetworkManager {
166
166
  });
167
167
 
168
168
  this._swarms.set(topic, swarm);
169
- this._signalConnection.join({ topic, peerId }).catch((error) => log.catch(error));
170
169
  this._mappers.set(topic, new SwarmMapper(swarm));
171
170
 
171
+ // Open before joining.
172
+ await swarm.open();
173
+
174
+ this._signalConnection.join({ topic, peerId }).catch((error) => log.catch(error));
175
+
172
176
  this.topicsUpdated.emit();
173
177
  this._connectionLog?.joinedSwarm(swarm);
174
178
  log('joined', { topic: PublicKey.from(topic), count: this._swarms.size });
@@ -112,6 +112,7 @@ describe('Signal Integration Test', () => {
112
112
  sessionId: PublicKey.random(),
113
113
  data: {
114
114
  signal: { payload: { message: 'Hello world!' } },
115
+ signalBatch: undefined,
115
116
  },
116
117
  };
117
118
  await peerNetworking1.messageRouter.signal(message);
@@ -129,6 +130,7 @@ describe('Signal Integration Test', () => {
129
130
  sessionId: PublicKey.random(),
130
131
  data: {
131
132
  signal: { payload: { foo: 'bar' } },
133
+ signalBatch: undefined,
132
134
  },
133
135
  };
134
136
  await peerNetworking2.messageRouter.signal(message);
@@ -3,7 +3,7 @@
3
3
  //
4
4
 
5
5
  import { PublicKey } from '@dxos/keys';
6
- import { Answer, Offer, Signal } from '@dxos/protocols/proto/dxos/mesh/swarm';
6
+ import { Answer, Offer, Signal, SignalBatch } from '@dxos/protocols/proto/dxos/mesh/swarm';
7
7
 
8
8
  export interface OfferMessage {
9
9
  author: PublicKey;
@@ -18,7 +18,7 @@ export interface SignalMessage {
18
18
  recipient: PublicKey;
19
19
  topic: PublicKey;
20
20
  sessionId: PublicKey;
21
- data: { signal: Signal };
21
+ data: { signal?: Signal; signalBatch?: SignalBatch };
22
22
  }
23
23
 
24
24
  /**
@@ -99,7 +99,10 @@ describe('SwarmMessenger', () => {
99
99
  recipient: peer1,
100
100
  sessionId: PublicKey.random(),
101
101
  topic,
102
- data: { signal: { payload: { msg: 'Some info' } } },
102
+ data: {
103
+ signal: { payload: { msg: 'Some info' } },
104
+ signalBatch: undefined,
105
+ },
103
106
  };
104
107
  await router2.signal(msg);
105
108
 
@@ -192,7 +195,7 @@ describe('SwarmMessenger', () => {
192
195
  recipient: peer3,
193
196
  sessionId: PublicKey.random(),
194
197
  topic,
195
- data: { signal: { payload: { msg: '1to3' } } },
198
+ data: { signal: { payload: { msg: '1to3' } }, signalBatch: undefined },
196
199
  };
197
200
  await router1.signal(msg1to3);
198
201
  await waitForExpect(() => {
@@ -205,7 +208,7 @@ describe('SwarmMessenger', () => {
205
208
  recipient: peer3,
206
209
  sessionId: PublicKey.random(),
207
210
  topic,
208
- data: { signal: { payload: { msg: '2to3' } } },
211
+ data: { signal: { payload: { msg: '2to3' } }, signalBatch: undefined },
209
212
  };
210
213
  await router2.signal(msg2to3);
211
214
  await waitForExpect(() => {
@@ -218,7 +221,7 @@ describe('SwarmMessenger', () => {
218
221
  recipient: peer1,
219
222
  sessionId: PublicKey.random(),
220
223
  topic,
221
- data: { signal: { payload: { msg: '3to1' } } },
224
+ data: { signal: { payload: { msg: '3to1' } }, signalBatch: undefined },
222
225
  };
223
226
  await router3.signal(msg3to1);
224
227
  await waitForExpect(() => {
@@ -73,11 +73,15 @@ export class SwarmMessenger implements SignalMessenger {
73
73
  await this._resolveAnswers(message);
74
74
  } else if (message.data?.signal) {
75
75
  await this._handleSignal({ author, recipient, message });
76
+ } else if (message.data?.signalBatch) {
77
+ await this._handleSignal({ author, recipient, message });
78
+ } else {
79
+ log.warn('unknown message', { message });
76
80
  }
77
81
  }
78
82
 
79
83
  async signal(message: SignalMessage): Promise<void> {
80
- assert(message.data?.signal);
84
+ assert(message.data?.signal || message.data?.signalBatch, 'Invalid message');
81
85
  await this._sendReliableMessage({
82
86
  author: message.author,
83
87
  recipient: message.recipient,
@@ -155,15 +159,19 @@ export class SwarmMessenger implements SignalMessenger {
155
159
  };
156
160
  const answer = await this._onOffer(offerMessage);
157
161
  answer.offerMessageId = message.messageId;
158
- await this._sendReliableMessage({
159
- author: recipient,
160
- recipient: author,
161
- message: {
162
- topic: message.topic,
163
- sessionId: message.sessionId,
164
- data: { answer },
165
- },
166
- });
162
+ try {
163
+ await this._sendReliableMessage({
164
+ author: recipient,
165
+ recipient: author,
166
+ message: {
167
+ topic: message.topic,
168
+ sessionId: message.sessionId,
169
+ data: { answer },
170
+ },
171
+ });
172
+ } catch (err) {
173
+ log.warn('error sending answer', { err });
174
+ }
167
175
  }
168
176
 
169
177
  private async _handleSignal({
@@ -176,12 +184,15 @@ export class SwarmMessenger implements SignalMessenger {
176
184
  message: SwarmMessage;
177
185
  }): Promise<void> {
178
186
  assert(message.messageId);
179
- assert(message.data.signal, 'No Signal');
187
+ assert(message.data.signal || message.data.signalBatch, 'Invalid message');
180
188
  const signalMessage: SignalMessage = {
181
189
  author,
182
190
  recipient,
183
191
  ...message,
184
- data: { signal: message.data.signal },
192
+ data: {
193
+ signal: message.data.signal,
194
+ signalBatch: message.data.signalBatch,
195
+ },
185
196
  };
186
197
 
187
198
  await this._onSignal(signalMessage);
@@ -4,8 +4,10 @@
4
4
 
5
5
  import assert from 'node:assert';
6
6
 
7
- import { Event, synchronized } from '@dxos/async';
7
+ import { DeferredTask, Event, sleep, synchronized } from '@dxos/async';
8
+ import { Context, cancelWithContext } from '@dxos/context';
8
9
  import { ErrorStream } from '@dxos/debug';
10
+ import { CancelledError } from '@dxos/errors';
9
11
  import { PublicKey } from '@dxos/keys';
10
12
  import { log } from '@dxos/log';
11
13
  import { trace } from '@dxos/protocols';
@@ -15,6 +17,17 @@ import { SignalMessage, SignalMessenger } from '../signal';
15
17
  import { Transport, TransportFactory } from '../transport';
16
18
  import { WireProtocol } from '../wire-protocol';
17
19
 
20
+ /**
21
+ * How long to wait before sending the signal in case we receive another signal.
22
+ * This value is increased exponentially.
23
+ */
24
+ const STARTING_SIGNALLING_DELAY = 10;
25
+
26
+ /**
27
+ * Maximum delay between signal batches.
28
+ */
29
+ const MAX_SIGNALLING_DELAY = 300;
30
+
18
31
  /**
19
32
  * State machine for each connection.
20
33
  */
@@ -51,15 +64,25 @@ export enum ConnectionState {
51
64
  * Owns a transport paired together with a wire-protocol.
52
65
  */
53
66
  export class Connection {
67
+ private readonly _ctx = new Context();
68
+
54
69
  private _state: ConnectionState = ConnectionState.INITIAL;
55
70
  private _transport: Transport | undefined;
56
- private _bufferedSignals: Signal[] = [];
71
+
72
+ private _incomingSignalBuffer: Signal[] = [];
73
+ private _outgoingSignalBuffer: Signal[] = [];
57
74
 
58
75
  readonly stateChanged = new Event<ConnectionState>();
59
76
  readonly errors = new ErrorStream();
60
77
 
61
78
  public _instanceId = PublicKey.random().toHex();
62
79
 
80
+ private readonly _signalSendTask = new DeferredTask(this._ctx, async () => {
81
+ await this._flushSignalBuffer();
82
+ });
83
+
84
+ private _signallingDelay = STARTING_SIGNALLING_DELAY;
85
+
63
86
  constructor(
64
87
  public readonly topic: PublicKey,
65
88
  public readonly ownId: PublicKey, // TODO(burdon): peerID?
@@ -108,21 +131,7 @@ export class Connection {
108
131
  this._transport = this._transportFactory.createTransport({
109
132
  initiator: this.initiator,
110
133
  stream: this._protocol.stream,
111
- sendSignal: async (signal) => {
112
- try {
113
- await this._signalMessaging.signal({
114
- author: this.ownId,
115
- recipient: this.remoteId,
116
- sessionId: this.sessionId,
117
- topic: this.topic,
118
- data: { signal },
119
- });
120
- } catch (err) {
121
- // If signal fails treat connection as failed
122
- log('Signal failed', { err });
123
- await this.close();
124
- }
125
- },
134
+ sendSignal: async (signal) => this._sendSignal(signal),
126
135
  });
127
136
 
128
137
  this._transport.connected.once(() => {
@@ -141,11 +150,11 @@ export class Connection {
141
150
  });
142
151
 
143
152
  // Replay signals that were received before transport was created.
144
- for (const signal of this._bufferedSignals) {
153
+ for (const signal of this._incomingSignalBuffer) {
145
154
  void this._transport.signal(signal); // TODO(burdon): Remove async?
146
155
  }
147
156
 
148
- this._bufferedSignals = [];
157
+ this._incomingSignalBuffer = [];
149
158
 
150
159
  log.trace('dxos.mesh.connection.open-connection', trace.end({ id: this._instanceId }));
151
160
  }
@@ -157,6 +166,8 @@ export class Connection {
157
166
  }
158
167
  this._changeState(ConnectionState.CLOSING);
159
168
 
169
+ await this._ctx.dispose();
170
+
160
171
  log('closing...', { peerId: this.ownId });
161
172
 
162
173
  try {
@@ -177,25 +188,69 @@ export class Connection {
177
188
  this._changeState(ConnectionState.CLOSED);
178
189
  }
179
190
 
191
+ private _sendSignal(signal: Signal) {
192
+ this._outgoingSignalBuffer.push(signal);
193
+ this._signalSendTask.schedule();
194
+ }
195
+
196
+ private async _flushSignalBuffer() {
197
+ if (this._outgoingSignalBuffer.length === 0) {
198
+ return;
199
+ }
200
+
201
+ try {
202
+ await cancelWithContext(this._ctx, sleep(this._signallingDelay));
203
+ this._signallingDelay = Math.min(this._signallingDelay * 2, MAX_SIGNALLING_DELAY);
204
+
205
+ const signals = [...this._outgoingSignalBuffer];
206
+ this._outgoingSignalBuffer.length = 0;
207
+
208
+ await this._signalMessaging.signal({
209
+ author: this.ownId,
210
+ recipient: this.remoteId,
211
+ sessionId: this.sessionId,
212
+ topic: this.topic,
213
+ data: { signalBatch: { signals } },
214
+ });
215
+ } catch (err) {
216
+ if (err instanceof CancelledError) {
217
+ return;
218
+ }
219
+
220
+ // If signal fails treat connection as failed
221
+ log.warn('Signal failed', { err });
222
+ await this.close();
223
+ }
224
+ }
225
+
226
+ /**
227
+ * Receive a signal from the remote peer.
228
+ */
180
229
  async signal(msg: SignalMessage) {
181
230
  assert(msg.sessionId);
182
231
  if (!msg.sessionId.equals(this.sessionId)) {
183
232
  log('dropping signal for incorrect session id');
184
233
  return;
185
234
  }
186
- assert(msg.data.signal);
235
+ assert(msg.data.signal || msg.data.signalBatch);
187
236
  assert(msg.author?.equals(this.remoteId));
188
237
  assert(msg.recipient?.equals(this.ownId));
189
238
 
190
- if (this._state === ConnectionState.INITIAL) {
191
- log('buffered signal', { peerId: this.ownId, remoteId: this.remoteId, msg: msg.data });
192
- this._bufferedSignals.push(msg.data.signal);
193
- return;
194
- }
239
+ const signals = msg.data.signalBatch ? msg.data.signalBatch.signals ?? [] : [msg.data.signal];
240
+ for (const signal of signals) {
241
+ if (!signal) {
242
+ continue;
243
+ }
195
244
 
196
- assert(this._transport, 'Connection not ready to accept signals.');
197
- log('received signal', { peerId: this.ownId, remoteId: this.remoteId, msg: msg.data });
198
- await this._transport.signal(msg.data.signal);
245
+ if (this._state === ConnectionState.INITIAL) {
246
+ log('buffered signal', { peerId: this.ownId, remoteId: this.remoteId, msg: msg.data });
247
+ this._incomingSignalBuffer.push(signal);
248
+ } else {
249
+ assert(this._transport, 'Connection not ready to accept signals.');
250
+ log('received signal', { peerId: this.ownId, remoteId: this.remoteId, msg: msg.data });
251
+ await this._transport.signal(signal);
252
+ }
253
+ }
199
254
  }
200
255
 
201
256
  private _changeState(state: ConnectionState): void {
@@ -26,7 +26,7 @@ describe('Swarm', () => {
26
26
  afterTest(() => signalManager.close());
27
27
  });
28
28
 
29
- const setupSwarm = ({ topic, peerId }: { topic: PublicKey; peerId: PublicKey }) => {
29
+ const setupSwarm = async ({ topic, peerId }: { topic: PublicKey; peerId: PublicKey }) => {
30
30
  const protocol = new TestWireProtocol(peerId);
31
31
  const swarm = new Swarm(
32
32
  topic,
@@ -42,6 +42,8 @@ describe('Swarm', () => {
42
42
  await swarm.destroy();
43
43
  });
44
44
 
45
+ await swarm.open();
46
+
45
47
  return { swarm, protocol };
46
48
  };
47
49
 
@@ -50,9 +52,9 @@ describe('Swarm', () => {
50
52
  const peerId1 = PublicKey.random();
51
53
  const peerId2 = PublicKey.random();
52
54
 
53
- const { swarm: swarm1, protocol: protocol1 } = setupSwarm({ topic, peerId: peerId1 });
55
+ const { swarm: swarm1, protocol: protocol1 } = await setupSwarm({ topic, peerId: peerId1 });
54
56
 
55
- const { swarm: swarm2 } = setupSwarm({ topic, peerId: peerId2 });
57
+ const { swarm: swarm2 } = await setupSwarm({ topic, peerId: peerId2 });
56
58
 
57
59
  expect(swarm1.connections.length).toEqual(0);
58
60
  expect(swarm2.connections.length).toEqual(0);
@@ -89,8 +91,8 @@ describe('Swarm', () => {
89
91
  const peerId1 = PublicKey.random();
90
92
  const peerId2 = PublicKey.random();
91
93
 
92
- const { swarm: swarm1 } = setupSwarm({ topic, peerId: peerId1 });
93
- const { swarm: swarm2 } = setupSwarm({ topic, peerId: peerId2 });
94
+ const { swarm: swarm1 } = await setupSwarm({ topic, peerId: peerId1 });
95
+ const { swarm: swarm2 } = await setupSwarm({ topic, peerId: peerId2 });
94
96
 
95
97
  expect(swarm1.connections.length).toEqual(0);
96
98
  expect(swarm2.connections.length).toEqual(0);
@@ -119,9 +121,9 @@ describe('Swarm', () => {
119
121
  const peerId1 = PublicKey.random();
120
122
  const peerId2 = PublicKey.random();
121
123
 
122
- const { swarm: swarm1, protocol: protocol1 } = setupSwarm({ topic, peerId: peerId1 });
124
+ const { swarm: swarm1, protocol: protocol1 } = await setupSwarm({ topic, peerId: peerId1 });
123
125
 
124
- const { swarm: swarm2 } = setupSwarm({ topic, peerId: peerId2 });
126
+ const { swarm: swarm2 } = await setupSwarm({ topic, peerId: peerId2 });
125
127
 
126
128
  expect(swarm1.connections.length).toEqual(0);
127
129
  expect(swarm2.connections.length).toEqual(0);
@@ -9,7 +9,7 @@ import { Context } from '@dxos/context';
9
9
  import { ErrorStream } from '@dxos/debug';
10
10
  import { PublicKey } from '@dxos/keys';
11
11
  import { log, logInfo } from '@dxos/log';
12
- import { Messenger } from '@dxos/messaging';
12
+ import { ListeningHandle, Messenger } from '@dxos/messaging';
13
13
  import { trace } from '@dxos/protocols';
14
14
  import { SwarmEvent } from '@dxos/protocols/proto/dxos/mesh/signal';
15
15
  import { Answer } from '@dxos/protocols/proto/dxos/mesh/swarm';
@@ -43,6 +43,8 @@ export class Swarm {
43
43
 
44
44
  private _ctx = new Context();
45
45
 
46
+ private _listeningHandle?: ListeningHandle = undefined;
47
+
46
48
  /**
47
49
  * Unique id of the swarm, local to the current peer, generated when swarm is joined.
48
50
  */
@@ -94,19 +96,6 @@ export class Swarm {
94
96
  onOffer: async (msg) => await this.onOffer(msg),
95
97
  topic: this._topic,
96
98
  });
97
-
98
- this._messenger
99
- .listen({
100
- peerId: this._ownPeerId,
101
- payloadType: 'dxos.mesh.swarm.SwarmMessage',
102
- onMessage: async (message) => {
103
- await this._swarmMessenger
104
- .receiveMessage(message)
105
- .catch((err) => log('Error while receiving message', { err }));
106
- },
107
- })
108
- .catch((error) => log.catch(error));
109
-
110
99
  log.trace('dxos.mesh.swarm.constructor', trace.end({ id: this._instanceId }));
111
100
  }
112
101
 
@@ -133,9 +122,24 @@ export class Swarm {
133
122
  return this._topic;
134
123
  }
135
124
 
136
- // TODO(burdon): async open?
125
+ async open() {
126
+ assert(!this._listeningHandle);
127
+ this._listeningHandle = await this._messenger.listen({
128
+ peerId: this._ownPeerId,
129
+ payloadType: 'dxos.mesh.swarm.SwarmMessage',
130
+ onMessage: async (message) => {
131
+ await this._swarmMessenger
132
+ .receiveMessage(message)
133
+ .catch((err) => log.warn('Error while receiving message', { err }));
134
+ },
135
+ });
136
+ }
137
+
137
138
  async destroy() {
138
139
  log('destroying...');
140
+ await this._listeningHandle?.unsubscribe();
141
+ this._listeningHandle = undefined;
142
+
139
143
  await this._ctx.dispose();
140
144
  await this._topology.destroy();
141
145
  await Promise.all(Array.from(this._peers.keys()).map((key) => this._destroyPeer(key)));