@streamr/dht 0.0.1-tatum.4 → 0.0.1-tatum.6

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.
Files changed (97) hide show
  1. package/dist/src/connection/ConnectionManager.d.ts +1 -0
  2. package/dist/src/connection/ConnectionManager.js +14 -2
  3. package/dist/src/connection/ConnectionManager.js.map +1 -1
  4. package/dist/src/connection/ConnectivityChecker.js +27 -17
  5. package/dist/src/connection/ConnectivityChecker.js.map +1 -1
  6. package/dist/src/connection/Handshaker.js +18 -13
  7. package/dist/src/connection/Handshaker.js.map +1 -1
  8. package/dist/src/connection/WebSocket/ServerWebSocket.js +0 -1
  9. package/dist/src/connection/WebSocket/ServerWebSocket.js.map +1 -1
  10. package/dist/src/dht/DhtNode.d.ts +2 -3
  11. package/dist/src/dht/DhtNode.js +24 -42
  12. package/dist/src/dht/DhtNode.js.map +1 -1
  13. package/dist/src/dht/DhtPeer.d.ts +2 -1
  14. package/dist/src/dht/DhtPeer.js +18 -25
  15. package/dist/src/dht/DhtPeer.js.map +1 -1
  16. package/dist/src/dht/RemoteExternalApi.d.ts +3 -1
  17. package/dist/src/dht/RemoteExternalApi.js +20 -6
  18. package/dist/src/dht/RemoteExternalApi.js.map +1 -1
  19. package/dist/src/dht/contact/Contact.d.ts +1 -15
  20. package/dist/src/dht/contact/Contact.js +1 -9
  21. package/dist/src/dht/contact/Contact.js.map +1 -1
  22. package/dist/src/dht/contact/ContactList.d.ts +27 -0
  23. package/dist/src/dht/contact/ContactList.js +44 -0
  24. package/dist/src/dht/contact/ContactList.js.map +1 -0
  25. package/dist/src/dht/contact/RandomContactList.d.ts +8 -16
  26. package/dist/src/dht/contact/RandomContactList.js +11 -36
  27. package/dist/src/dht/contact/RandomContactList.js.map +1 -1
  28. package/dist/src/dht/contact/Remote.d.ts +10 -10
  29. package/dist/src/dht/contact/Remote.js +17 -9
  30. package/dist/src/dht/contact/Remote.js.map +1 -1
  31. package/dist/src/dht/contact/SortedContactList.d.ts +11 -20
  32. package/dist/src/dht/contact/SortedContactList.js +17 -39
  33. package/dist/src/dht/contact/SortedContactList.js.map +1 -1
  34. package/dist/src/dht/find/RecursiveFinder.js +1 -1
  35. package/dist/src/dht/find/RecursiveFinder.js.map +1 -1
  36. package/dist/src/dht/find/RemoteRecursiveFindSession.js +1 -5
  37. package/dist/src/dht/find/RemoteRecursiveFindSession.js.map +1 -1
  38. package/dist/src/dht/registerExternalApiRpcMethods.d.ts +2 -0
  39. package/dist/src/dht/{registerExternalApiRpcMethod.js → registerExternalApiRpcMethods.js} +13 -5
  40. package/dist/src/dht/registerExternalApiRpcMethods.js.map +1 -0
  41. package/dist/src/dht/routing/RemoteRouter.js +13 -19
  42. package/dist/src/dht/routing/RemoteRouter.js.map +1 -1
  43. package/dist/src/dht/routing/RoutingSession.d.ts +0 -1
  44. package/dist/src/dht/routing/RoutingSession.js +15 -10
  45. package/dist/src/dht/routing/RoutingSession.js.map +1 -1
  46. package/dist/src/dht/store/DataStore.js +3 -3
  47. package/dist/src/dht/store/DataStore.js.map +1 -1
  48. package/dist/src/dht/store/RemoteStore.js +13 -17
  49. package/dist/src/dht/store/RemoteStore.js.map +1 -1
  50. package/dist/src/exports.d.ts +1 -1
  51. package/dist/src/exports.js +3 -3
  52. package/dist/src/exports.js.map +1 -1
  53. package/dist/src/proto/packages/dht/protos/DhtRpc.client.d.ts +10 -0
  54. package/dist/src/proto/packages/dht/protos/DhtRpc.client.js +7 -0
  55. package/dist/src/proto/packages/dht/protos/DhtRpc.client.js.map +1 -1
  56. package/dist/src/proto/packages/dht/protos/DhtRpc.d.ts +36 -0
  57. package/dist/src/proto/packages/dht/protos/DhtRpc.js +29 -2
  58. package/dist/src/proto/packages/dht/protos/DhtRpc.js.map +1 -1
  59. package/dist/src/proto/packages/dht/protos/DhtRpc.server.d.ts +6 -0
  60. package/package.json +6 -6
  61. package/protos/DhtRpc.proto +10 -0
  62. package/src/connection/ConnectionManager.ts +17 -4
  63. package/src/connection/ConnectivityChecker.ts +26 -17
  64. package/src/connection/Handshaker.ts +18 -13
  65. package/src/connection/WebSocket/ServerWebSocket.ts +0 -1
  66. package/src/dht/DhtNode.ts +36 -25
  67. package/src/dht/DhtPeer.ts +20 -27
  68. package/src/dht/RemoteExternalApi.ts +22 -8
  69. package/src/dht/contact/Contact.ts +1 -18
  70. package/src/dht/contact/ContactList.ts +59 -0
  71. package/src/dht/contact/RandomContactList.ts +17 -43
  72. package/src/dht/contact/Remote.ts +27 -20
  73. package/src/dht/contact/SortedContactList.ts +29 -58
  74. package/src/dht/find/RecursiveFinder.ts +3 -3
  75. package/src/dht/find/RemoteRecursiveFindSession.ts +1 -8
  76. package/src/dht/registerExternalApiRpcMethods.ts +41 -0
  77. package/src/dht/routing/RemoteRouter.ts +13 -20
  78. package/src/dht/routing/RoutingSession.ts +29 -20
  79. package/src/dht/store/DataStore.ts +6 -6
  80. package/src/dht/store/RemoteStore.ts +13 -20
  81. package/src/exports.ts +1 -1
  82. package/src/proto/packages/dht/protos/DhtRpc.client.ts +13 -0
  83. package/src/proto/packages/dht/protos/DhtRpc.server.ts +6 -0
  84. package/src/proto/packages/dht/protos/DhtRpc.ts +49 -1
  85. package/test/benchmark/KademliaCorrectness.test.ts +2 -1
  86. package/test/end-to-end/Layer0-Layer1.test.ts +10 -10
  87. package/test/integration/DhtNodeExternalAPI.test.ts +9 -0
  88. package/test/integration/DhtWithMockConnectionLatencies.test.ts +1 -1
  89. package/test/integration/DhtWithMockConnections.test.ts +1 -1
  90. package/test/integration/DhtWithRealConnectionLatencies.test.ts +1 -1
  91. package/test/integration/RemoteRouter.test.ts +1 -1
  92. package/test/integration/RemoteStore.test.ts +1 -1
  93. package/test/unit/RandomContactList.test.ts +31 -73
  94. package/test/unit/SortedContactList.test.ts +72 -96
  95. package/dist/src/dht/registerExternalApiRpcMethod.d.ts +0 -2
  96. package/dist/src/dht/registerExternalApiRpcMethod.js.map +0 -1
  97. package/src/dht/registerExternalApiRpcMethod.ts +0 -26
@@ -32,21 +32,26 @@ export class Handshaker extends EventEmitter<HandshakerEvents> {
32
32
  }
33
33
 
34
34
  private onData = (data: Uint8Array) => {
35
- const message = Message.fromBinary(data)
36
- if (message.body.oneofKind === 'handshakeRequest') {
37
- logger.trace('handshake request received')
38
- const handshake = message.body.handshakeRequest
39
- this.emit('handshakeRequest', handshake.peerDescriptor!)
40
- }
41
- if (message.body.oneofKind === 'handshakeResponse') {
42
- logger.trace('handshake response received')
43
- const handshake = message.body.handshakeResponse
44
- if (handshake.responseError) {
45
- this.emit('handshakeFailed', handshake.responseError)
46
- } else {
47
- this.emit('handshakeCompleted', handshake.peerDescriptor!)
35
+ try {
36
+ const message = Message.fromBinary(data)
37
+ if (message.body.oneofKind === 'handshakeRequest') {
38
+ logger.trace('handshake request received')
39
+ const handshake = message.body.handshakeRequest
40
+ this.emit('handshakeRequest', handshake.peerDescriptor!)
41
+ }
42
+ if (message.body.oneofKind === 'handshakeResponse') {
43
+ logger.trace('handshake response received')
44
+ const handshake = message.body.handshakeResponse
45
+ if (handshake.responseError) {
46
+ this.emit('handshakeFailed', handshake.responseError)
47
+ } else {
48
+ this.emit('handshakeCompleted', handshake.peerDescriptor!)
49
+ }
48
50
  }
51
+ } catch (err) {
52
+ logger.error('error while parsing handshake message', err)
49
53
  }
54
+
50
55
  }
51
56
 
52
57
  public sendHandshakeRequest(): void {
@@ -67,7 +67,6 @@ export class ServerWebSocket extends EventEmitter<ConnectionEvents> implements I
67
67
  this.socket = undefined
68
68
 
69
69
  this.emit('disconnected', disconnectionType, reasonCode, description)
70
- this.removeAllListeners()
71
70
  }
72
71
 
73
72
  public send(data: Uint8Array): void {
@@ -18,7 +18,6 @@ import {
18
18
  FindMode,
19
19
  DataEntry,
20
20
  } from '../proto/packages/dht/protos/DhtRpc'
21
- import * as Err from '../helpers/errors'
22
21
  import { DisconnectionType, ITransport, TransportEvents } from '../transport/ITransport'
23
22
  import { ConnectionManager, ConnectionManagerConfig, PortRange, TlsCertificate } from '../connection/ConnectionManager'
24
23
  import { DhtRpcServiceClient, ExternalApiServiceClient } from '../proto/packages/dht/protos/DhtRpc.client'
@@ -40,10 +39,11 @@ import { DataStore } from './store/DataStore'
40
39
  import { PeerDiscovery } from './discovery/PeerDiscovery'
41
40
  import { LocalDataStore } from './store/LocalDataStore'
42
41
  import { IceServer } from '../connection/WebRTC/WebRtcConnector'
43
- import { registerExternalApiRpcMethod } from './registerExternalApiRpcMethod'
42
+ import { registerExternalApiRpcMethods } from './registerExternalApiRpcMethods'
44
43
  import { RemoteExternalApi } from './RemoteExternalApi'
45
44
  import { UUID } from '../exports'
46
45
  import { isNodeJS } from '../helpers/browser/isNodeJS'
46
+ import { sample } from 'lodash'
47
47
 
48
48
  export interface DhtNodeEvents {
49
49
  newContact: (peerDescriptor: PeerDescriptor, closestPeers: PeerDescriptor[]) => void
@@ -142,7 +142,8 @@ export const createPeerDescriptor = (msg?: ConnectivityResponse, peerId?: string
142
142
  } else {
143
143
  kademliaId = hexToBinary(peerId!)
144
144
  }
145
- const ret: PeerDescriptor = { kademliaId, nodeName: nodeName ? nodeName : binaryToHex(kademliaId), type: NodeType.NODEJS }
145
+ const nodeType = isNodeJS() ? NodeType.NODEJS : NodeType.BROWSER
146
+ const ret: PeerDescriptor = { kademliaId, nodeName: nodeName ? nodeName : binaryToHex(kademliaId), type: nodeType }
146
147
  if (msg && msg.websocket) {
147
148
  ret.websocket = { host: msg.websocket.host, port: msg.websocket.port, tls: msg.websocket.tls }
148
149
  ret.openInternet = true
@@ -299,7 +300,7 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
299
300
  return this.bucket!.closest(id, n)
300
301
  }
301
302
  })
302
- registerExternalApiRpcMethod(this)
303
+ registerExternalApiRpcMethods(this)
303
304
  if (this.connectionManager! && this.config.entryPoints && this.config.entryPoints.length > 0
304
305
  && !isSamePeerDescriptor(this.config.entryPoints[0], this.ownPeerDescriptor!)) {
305
306
  this.connectToEntryPoint(this.config.entryPoints[0])
@@ -319,29 +320,29 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
319
320
  // TODO: Update contact info to the connection manager and reconnect
320
321
  })
321
322
  this.neighborList = new SortedContactList(selfId, this.config.maxNeighborListSize)
322
- this.neighborList.on('contactRemoved', (peerDescriptor: PeerDescriptor, activeContacts: PeerDescriptor[]) => {
323
+ this.neighborList.on('contactRemoved', (removedContact: DhtPeer, activeContacts: DhtPeer[]) => {
323
324
  if (this.stopped) {
324
325
  return
325
326
  }
326
- this.emit('contactRemoved', peerDescriptor, activeContacts)
327
+ this.emit('contactRemoved', removedContact.getPeerDescriptor(), activeContacts.map((c) => c.getPeerDescriptor()))
327
328
  this.randomPeers!.addContact(
328
329
  new DhtPeer(
329
330
  this.ownPeerDescriptor!,
330
- peerDescriptor,
331
+ removedContact.getPeerDescriptor(),
331
332
  toProtoRpcClient(new DhtRpcServiceClient(this.rpcCommunicator!.getRpcClientTransport())),
332
333
  this.config.serviceId
333
334
  )
334
335
  )
335
336
  })
336
- this.neighborList.on('newContact', (peerDescriptor: PeerDescriptor, activeContacts: PeerDescriptor[]) =>
337
- this.emit('newContact', peerDescriptor, activeContacts)
337
+ this.neighborList.on('newContact', (newContact: DhtPeer, activeContacts: DhtPeer[]) =>
338
+ this.emit('newContact', newContact.getPeerDescriptor(), activeContacts.map((c) => c.getPeerDescriptor()))
338
339
  )
339
340
  this.openInternetPeers = new SortedContactList(selfId, this.config.maxNeighborListSize / 2)
340
- this.openInternetPeers.on('contactRemoved', (peerDescriptor: PeerDescriptor, activeContacts: PeerDescriptor[]) =>
341
- this.emit('openInternetContactRemoved', peerDescriptor, activeContacts)
341
+ this.openInternetPeers.on('contactRemoved', (removedContact: DhtPeer, activeContacts: DhtPeer[]) =>
342
+ this.emit('openInternetContactRemoved', removedContact.getPeerDescriptor(), activeContacts.map((c) => c.getPeerDescriptor()))
342
343
  )
343
- this.openInternetPeers.on('newContact', (peerDescriptor: PeerDescriptor, activeContacts: PeerDescriptor[]) =>
344
- this.emit('newOpenInternetContact', peerDescriptor, activeContacts)
344
+ this.openInternetPeers.on('newContact', (newContact: DhtPeer, activeContacts: DhtPeer[]) =>
345
+ this.emit('newOpenInternetContact', newContact.getPeerDescriptor(), activeContacts.map((c) => c.getPeerDescriptor()))
345
346
  )
346
347
  this.transportLayer!.on('connected', (peerDescriptor: PeerDescriptor) => this.onTransportConnected(peerDescriptor))
347
348
 
@@ -363,11 +364,11 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
363
364
  this.connections.set(peerId.toKey(), dhtPeer)
364
365
  })
365
366
  this.randomPeers = new RandomContactList(selfId, this.config.maxNeighborListSize)
366
- this.randomPeers.on('contactRemoved', (peerDescriptor: PeerDescriptor, activeContacts: PeerDescriptor[]) =>
367
- this.emit('randomContactRemoved', peerDescriptor, activeContacts)
367
+ this.randomPeers.on('contactRemoved', (removedContact: DhtPeer, activeContacts: DhtPeer[]) =>
368
+ this.emit('randomContactRemoved', removedContact.getPeerDescriptor(), activeContacts.map((c) => c.getPeerDescriptor()))
368
369
  )
369
- this.randomPeers.on('newContact', (peerDescriptor: PeerDescriptor, activeContacts: PeerDescriptor[]) =>
370
- this.emit('newRandomContact', peerDescriptor, activeContacts)
370
+ this.randomPeers.on('newContact', (newContact: DhtPeer, activeContacts: DhtPeer[]) =>
371
+ this.emit('newRandomContact', newContact.getPeerDescriptor(), activeContacts.map((c) => c.getPeerDescriptor()))
371
372
  )
372
373
  }
373
374
 
@@ -555,8 +556,8 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
555
556
  return undefined
556
557
  }
557
558
 
558
- public getNeighborList(): SortedContactList<DhtPeer> {
559
- return this.neighborList!
559
+ public getClosestContacts(maxCount?: number): PeerDescriptor[] {
560
+ return this.neighborList!.getClosestContacts(maxCount).map((c) => c.getPeerDescriptor())
560
561
  }
561
562
 
562
563
  public getNodeId(): PeerID {
@@ -640,9 +641,22 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
640
641
  }
641
642
 
642
643
  public async storeDataToDht(key: Uint8Array, data: Any): Promise<PeerDescriptor[]> {
644
+ if (this.isJoinOngoing() && this.config.entryPoints && this.config.entryPoints.length > 0) {
645
+ return this.storeDataViaPeer(key, data, sample(this.config.entryPoints)!)
646
+ }
643
647
  return this.dataStore!.storeDataToDht(key, data)
644
648
  }
645
649
 
650
+ public async storeDataViaPeer(key: Uint8Array, data: Any, peer: PeerDescriptor): Promise<PeerDescriptor[]> {
651
+ const target = new RemoteExternalApi(
652
+ this.ownPeerDescriptor!,
653
+ peer,
654
+ this.config.serviceId,
655
+ toProtoRpcClient(new ExternalApiServiceClient(this.rpcCommunicator!.getRpcClientTransport()))
656
+ )
657
+ return await target.storeData(key, data)
658
+ }
659
+
646
660
  public async getDataFromDht(idToFind: Uint8Array): Promise<RecursiveFindResult> {
647
661
  return this.recursiveFinder!.startRecursiveFind(idToFind, FindMode.DATA)
648
662
  }
@@ -657,8 +671,8 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
657
671
  const target = new RemoteExternalApi(
658
672
  this.ownPeerDescriptor!,
659
673
  peer,
660
- toProtoRpcClient(new ExternalApiServiceClient(this.rpcCommunicator!.getRpcClientTransport())),
661
- this.config.serviceId
674
+ this.config.serviceId,
675
+ toProtoRpcClient(new ExternalApiServiceClient(this.rpcCommunicator!.getRpcClientTransport()))
662
676
  )
663
677
  return await target.findData(idToFind)
664
678
  }
@@ -720,13 +734,10 @@ export class DhtNode extends EventEmitter<Events> implements ITransport {
720
734
  }
721
735
 
722
736
  public async stop(): Promise<void> {
723
- if (this.stopped) {
737
+ if (this.stopped || !this.started) {
724
738
  return
725
739
  }
726
740
  logger.trace('stop()')
727
- if (!this.started) {
728
- throw new Err.CouldNotStop('Cannot not stop() before start()')
729
- }
730
741
  this.stopped = true
731
742
 
732
743
  if (this.entryPointDisconnectTimeout) {
@@ -6,10 +6,10 @@ import {
6
6
  PingRequest
7
7
  } from '../proto/packages/dht/protos/DhtRpc'
8
8
  import { v4 } from 'uuid'
9
- import { DhtRpcOptions } from '../rpc-protocol/DhtRpcOptions'
10
9
  import { Logger } from '@streamr/utils'
11
10
  import { ProtoRpcClient } from '@streamr/proto-rpc'
12
11
  import { Remote } from './contact/Remote'
12
+ import { PeerID, peerIdFromPeerDescriptor } from '../exports'
13
13
 
14
14
  const logger = new Logger(module)
15
15
 
@@ -20,77 +20,70 @@ export interface KBucketContact {
20
20
  }
21
21
 
22
22
  export class DhtPeer extends Remote<IDhtRpcServiceClient> implements KBucketContact {
23
+
23
24
  private static counter = 0
24
25
  public vectorClock: number
25
26
  public readonly id: Uint8Array
27
+
26
28
  constructor(
27
29
  ownPeerDescriptor: PeerDescriptor,
28
30
  peerDescriptor: PeerDescriptor,
29
31
  client: ProtoRpcClient<IDhtRpcServiceClient>,
30
32
  serviceId: string
31
33
  ) {
32
- super(ownPeerDescriptor, peerDescriptor, client, serviceId)
33
- this.id = this.peerId.value
34
+ super(ownPeerDescriptor, peerDescriptor, serviceId, client)
35
+ this.id = this.getPeerId().value
34
36
  this.vectorClock = DhtPeer.counter++
35
37
  }
36
38
 
37
39
  async getClosestPeers(kademliaId: Uint8Array): Promise<PeerDescriptor[]> {
38
- logger.trace(`Requesting getClosestPeers on ${this.serviceId} from ${this.peerId.toKey()}`)
40
+ logger.trace(`Requesting getClosestPeers on ${this.getServiceId()} from ${this.getPeerId().toKey()}`)
39
41
  const request: ClosestPeersRequest = {
40
42
  kademliaId,
41
43
  requestId: v4()
42
44
  }
43
- const options: DhtRpcOptions = {
44
- sourceDescriptor: this.ownPeerDescriptor,
45
- targetDescriptor: this.peerDescriptor
46
- }
47
45
  try {
48
- const peers = await this.client.getClosestPeers(request, options)
46
+ const peers = await this.getClient().getClosestPeers(request, this.formDhtRpcOptions())
49
47
  return peers.peers
50
48
  } catch (err) {
51
- logger.trace(`getClosestPeers error ${this.serviceId}`, { err })
49
+ logger.trace(`getClosestPeers error ${this.getServiceId()}`, { err })
52
50
  throw err
53
51
  }
54
52
  }
55
53
 
56
54
  async ping(): Promise<boolean> {
57
- logger.trace(`Requesting ping on ${this.serviceId} from ${this.peerId.toKey()}`)
55
+ logger.trace(`Requesting ping on ${this.getServiceId()} from ${this.getPeerId().toKey()}`)
58
56
  const request: PingRequest = {
59
57
  requestId: v4()
60
58
  }
61
- const options: DhtRpcOptions = {
62
- sourceDescriptor: this.ownPeerDescriptor,
63
- targetDescriptor: this.peerDescriptor,
59
+ const options = this.formDhtRpcOptions({
64
60
  timeout: 10000
65
- }
61
+ })
66
62
  try {
67
- const pong = await this.client.ping(request, options)
63
+ const pong = await this.getClient().ping(request, options)
68
64
  if (pong.requestId === request.requestId) {
69
65
  return true
70
66
  }
71
67
  } catch (err) {
72
- logger.trace(`ping failed on ${this.serviceId} to ${this.peerId.toKey()}: ${err}`)
68
+ logger.trace(`ping failed on ${this.getServiceId()} to ${this.getPeerId().toKey()}: ${err}`)
73
69
  }
74
70
  return false
75
71
  }
76
72
 
77
73
  leaveNotice(): void {
78
- logger.trace(`Sending leaveNotice on ${this.serviceId} from ${this.peerId.toKey()}`)
74
+ logger.trace(`Sending leaveNotice on ${this.getServiceId()} from ${this.getPeerId().toKey()}`)
79
75
  const request: LeaveNotice = {
80
- serviceId: this.serviceId
76
+ serviceId: this.getServiceId()
81
77
  }
82
- const options: DhtRpcOptions = {
83
- sourceDescriptor: this.ownPeerDescriptor,
84
- targetDescriptor: this.peerDescriptor,
78
+ const options = this.formDhtRpcOptions({
85
79
  notification: true
86
- }
87
- this.client.leaveNotice(request, options).catch((e) => {
80
+ })
81
+ this.getClient().leaveNotice(request, options).catch((e) => {
88
82
  logger.trace('Failed to send leaveNotice' + e)
89
83
  })
90
84
  }
91
85
 
92
- getPeerDescriptor(): PeerDescriptor {
93
- return this.peerDescriptor
86
+ getPeerId(): PeerID {
87
+ return peerIdFromPeerDescriptor(this.getPeerDescriptor())
94
88
  }
95
-
96
89
  }
@@ -1,5 +1,5 @@
1
- import { DhtRpcOptions } from '../exports'
2
- import { DataEntry, FindDataRequest } from '../proto/packages/dht/protos/DhtRpc'
1
+ import { Any } from '../proto/google/protobuf/any'
2
+ import { DataEntry, ExternalStoreDataRequest, FindDataRequest, PeerDescriptor } from '../proto/packages/dht/protos/DhtRpc'
3
3
  import { IExternalApiServiceClient } from '../proto/packages/dht/protos/DhtRpc.client'
4
4
  import { Remote } from './contact/Remote'
5
5
 
@@ -8,18 +8,32 @@ export class RemoteExternalApi extends Remote<IExternalApiServiceClient> {
8
8
  async findData(idToFind: Uint8Array): Promise<DataEntry[]> {
9
9
  const request: FindDataRequest = {
10
10
  kademliaId: idToFind,
11
- requestor: this.ownPeerDescriptor,
11
+ requestor: this.getLocalPeerDescriptor(),
12
12
  }
13
- const options: DhtRpcOptions = {
14
- sourceDescriptor: this.ownPeerDescriptor,
15
- targetDescriptor: this.peerDescriptor,
13
+ const options = this.formDhtRpcOptions({
16
14
  timeout: 10000
17
- }
15
+ })
18
16
  try {
19
- const data = await this.client.findData(request, options)
17
+ const data = await this.getClient().findData(request, options)
20
18
  return data.dataEntries
21
19
  } catch (err) {
22
20
  return []
23
21
  }
24
22
  }
23
+
24
+ async storeData(key: Uint8Array, data: Any): Promise<PeerDescriptor[]> {
25
+ const request: ExternalStoreDataRequest = {
26
+ key,
27
+ data
28
+ }
29
+ const options = this.formDhtRpcOptions({
30
+ timeout: 10000
31
+ })
32
+ try {
33
+ const response = await this.getClient().externalStoreData(request, options)
34
+ return response.storers
35
+ } catch (err) {
36
+ return []
37
+ }
38
+ }
25
39
  }
@@ -2,24 +2,7 @@ import { PeerID } from '../../helpers/PeerID'
2
2
  import { PeerDescriptor } from '../../proto/packages/dht/protos/DhtRpc'
3
3
  import { peerIdFromPeerDescriptor } from '../../helpers/peerIdFromPeerDescriptor'
4
4
 
5
- export class ContactState<TContact> {
6
- public contacted = false
7
- public active = false
8
- public contact: TContact
9
-
10
- constructor(contact: TContact) {
11
- this.contact = contact
12
- }
13
- }
14
-
15
- export interface IContact { getPeerId: () => PeerID, getPeerDescriptor: () => PeerDescriptor }
16
-
17
- export interface Events {
18
- contactRemoved: (removedDescriptor: PeerDescriptor, closestDescriptors: PeerDescriptor[]) => void
19
- newContact: (newDescriptor: PeerDescriptor, closestDescriptors: PeerDescriptor[]) => void
20
- }
21
-
22
- export class Contact implements IContact {
5
+ export class Contact {
23
6
  private peerDescriptor: PeerDescriptor
24
7
 
25
8
  constructor(peerDescriptor: PeerDescriptor) {
@@ -0,0 +1,59 @@
1
+ import { PeerID, PeerIDKey } from '../../helpers/PeerID'
2
+ import EventEmitter from 'eventemitter3'
3
+
4
+ export class ContactState<C> {
5
+ public contacted = false
6
+ public active = false
7
+ public contact: C
8
+
9
+ constructor(contact: C) {
10
+ this.contact = contact
11
+ }
12
+ }
13
+
14
+ export interface Events<C> {
15
+ contactRemoved: (removedContact: C, closestContacts: C[]) => void
16
+ newContact: (newContact: C, closestContacts: C[]) => void
17
+ }
18
+
19
+ export class ContactList<C extends { getPeerId: () => PeerID }> extends EventEmitter<Events<C>> {
20
+
21
+ protected contactsById: Map<PeerIDKey, ContactState<C>> = new Map()
22
+ protected contactIds: PeerID[] = []
23
+ protected ownId: PeerID
24
+ protected maxSize: number
25
+ protected defaultContactQueryLimit
26
+
27
+ constructor(
28
+ ownId: PeerID,
29
+ maxSize: number,
30
+ defaultContactQueryLimit = 20
31
+ ) {
32
+ super()
33
+ this.ownId = ownId
34
+ this.maxSize = maxSize
35
+ this.defaultContactQueryLimit = defaultContactQueryLimit
36
+ }
37
+
38
+ public getContact(id: PeerID): ContactState<C> {
39
+ return this.contactsById.get(id.toKey())!
40
+ }
41
+
42
+ public hasContact(id: PeerID): boolean {
43
+ return this.contactsById.has(id.toKey())
44
+ }
45
+
46
+ public getSize(): number {
47
+ return this.contactIds.length
48
+ }
49
+
50
+ public clear(): void {
51
+ this.contactsById.clear()
52
+ this.contactIds = []
53
+ }
54
+
55
+ public stop(): void {
56
+ this.removeAllListeners()
57
+ this.clear()
58
+ }
59
+ }
@@ -1,29 +1,21 @@
1
- import { Events, IContact, ContactState } from './Contact'
1
+ import { PeerID } from '../../helpers/PeerID'
2
+ import { ContactList, ContactState } from './ContactList'
2
3
 
3
- import EventEmitter from 'eventemitter3'
4
- import { PeerID, PeerIDKey } from '../../helpers/PeerID'
5
- export class RandomContactList<Contact extends IContact> extends EventEmitter<Events> {
6
- private contactsById: Map<PeerIDKey, ContactState<Contact>> = new Map()
7
- private contactIds: PeerID[] = []
8
- private ownId: PeerID
9
- private maxSize: number
10
- private randomness = 0.20
11
- private getContactsLimit = 20
4
+ export class RandomContactList<C extends { getPeerId: () => PeerID }> extends ContactList<C> {
5
+
6
+ private randomness: number
12
7
 
13
8
  constructor(
14
9
  ownId: PeerID,
15
10
  maxSize: number,
16
11
  randomness = 0.20,
17
- getContactsLimit = 20
12
+ defaultContactQueryLimit?: number
18
13
  ) {
19
- super()
20
- this.ownId = ownId
21
- this.maxSize = maxSize
14
+ super(ownId, maxSize, defaultContactQueryLimit)
22
15
  this.randomness = randomness
23
- this.getContactsLimit = getContactsLimit
24
16
  }
25
17
 
26
- addContact(contact: Contact): void {
18
+ addContact(contact: C): void {
27
19
  if (this.ownId.equals(contact.getPeerId())) {
28
20
  return
29
21
  }
@@ -38,55 +30,37 @@ export class RandomContactList<Contact extends IContact> extends EventEmitter<Ev
38
30
  this.contactsById.set(contact.getPeerId().toKey(), new ContactState(contact))
39
31
  this.emit(
40
32
  'newContact',
41
- contact.getPeerDescriptor(),
42
- this.getContacts().map((contact: Contact) => contact.getPeerDescriptor())
33
+ contact,
34
+ this.getContacts()
43
35
  )
44
36
  }
45
37
  }
46
38
  }
47
39
 
48
- addContacts(contacts: Contact[]): void {
40
+ addContacts(contacts: C[]): void {
49
41
  contacts.forEach((contact) => this.addContact(contact))
50
42
  }
51
43
 
52
44
  removeContact(id: PeerID): boolean {
53
45
  if (this.contactsById.has(id.toKey())) {
54
- const removedDescriptor = this.contactsById.get(id.toKey())!.contact.getPeerDescriptor()
55
- const index = this.contactIds.indexOf(id)
46
+ const removed = this.contactsById.get(id.toKey())!.contact
47
+ const index = this.contactIds.findIndex((element) => element.equals(id))
56
48
  this.contactIds.splice(index, 1)
57
49
  this.contactsById.delete(id.toKey())
58
- this.emit('contactRemoved', removedDescriptor, this.getContacts().map((contact: Contact) => contact.getPeerDescriptor()))
50
+ this.emit('contactRemoved', removed, this.getContacts())
59
51
  return true
60
52
  }
61
53
  return false
62
54
  }
63
55
 
64
- public getSize(): number {
65
- return this.contactIds.length
66
- }
67
-
68
- public getContact(id: PeerID): ContactState<Contact> {
69
- return this.contactsById.get(id.toKey())!
70
- }
71
-
72
- public getContacts(limit = this.getContactsLimit): Contact[] {
73
- const ret: Contact[] = []
56
+ public getContacts(limit = this.defaultContactQueryLimit): C[] {
57
+ const ret: C[] = []
74
58
  this.contactIds.forEach((contactId) => {
75
59
  const contact = this.contactsById.get(contactId.toKey())
76
60
  if (contact) {
77
61
  ret.push(contact.contact)
78
62
  }
79
63
  })
80
- return ret.splice(0, limit)
81
- }
82
-
83
- public clear(): void {
84
- this.contactsById.clear()
85
- this.contactIds = []
86
- }
87
-
88
- public stop(): void {
89
- this.removeAllListeners()
90
- this.clear()
64
+ return ret.slice(0, limit)
91
65
  }
92
66
  }
@@ -1,40 +1,47 @@
1
1
  import { PeerDescriptor } from '../../proto/packages/dht/protos/DhtRpc'
2
2
  import { ProtoRpcClient } from '@streamr/proto-rpc'
3
- import { peerIdFromPeerDescriptor } from '../../helpers/peerIdFromPeerDescriptor'
4
- import { PeerID } from '../../helpers/PeerID'
5
- import { IContact } from './Contact'
3
+ import { DhtRpcOptions } from '../../rpc-protocol/DhtRpcOptions'
6
4
 
7
- export abstract class Remote<T> implements IContact {
5
+ export abstract class Remote<T> {
8
6
 
9
- protected readonly peerId: PeerID
10
- protected readonly peerDescriptor: PeerDescriptor
11
- protected readonly client: ProtoRpcClient<T>
12
- protected readonly serviceId: string
13
- protected readonly ownPeerDescriptor: PeerDescriptor
7
+ private readonly localPeerDescriptor: PeerDescriptor
8
+ private readonly remotePeerDescriptor: PeerDescriptor
9
+ private readonly serviceId: string
10
+ private readonly client: ProtoRpcClient<T>
14
11
 
15
12
  constructor(
16
- ownPeerDescriptor: PeerDescriptor,
17
- peerDescriptor: PeerDescriptor,
18
- client: ProtoRpcClient<T>,
19
- serviceId: string
13
+ localPeerDescriptor: PeerDescriptor,
14
+ remotePeerDescriptor: PeerDescriptor,
15
+ serviceId: string,
16
+ client: ProtoRpcClient<T>
20
17
  ) {
21
- this.ownPeerDescriptor = ownPeerDescriptor
22
- this.peerId = peerIdFromPeerDescriptor(peerDescriptor)
23
- this.peerDescriptor = peerDescriptor
18
+ this.localPeerDescriptor = localPeerDescriptor
19
+ this.remotePeerDescriptor = remotePeerDescriptor
24
20
  this.client = client
25
21
  this.serviceId = serviceId
26
22
  }
27
23
 
28
- getPeerId(): PeerID {
29
- return this.peerId
24
+ getPeerDescriptor(): PeerDescriptor {
25
+ return this.remotePeerDescriptor
30
26
  }
31
27
 
32
- getPeerDescriptor(): PeerDescriptor {
33
- return this.peerDescriptor
28
+ getLocalPeerDescriptor(): PeerDescriptor {
29
+ return this.localPeerDescriptor
34
30
  }
35
31
 
36
32
  getServiceId(): string {
37
33
  return this.serviceId
38
34
  }
39
35
 
36
+ getClient(): ProtoRpcClient<T> {
37
+ return this.client
38
+ }
39
+
40
+ formDhtRpcOptions(opts?: Omit<DhtRpcOptions, 'sourceDescriptor' | 'targetDescriptor'>): DhtRpcOptions {
41
+ return {
42
+ sourceDescriptor: this.localPeerDescriptor,
43
+ targetDescriptor: this.remotePeerDescriptor,
44
+ ...opts
45
+ }
46
+ }
40
47
  }