webpeerjs 0.1.10 → 0.2.1

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,6 +1,6 @@
1
1
  //! WebPEER.js -- https://github.com/nuzulul/webpeerjs
2
2
 
3
- import * as config from './config'
3
+ import * as config from './config.js'
4
4
  import {
5
5
  mkErr,
6
6
  PBPeer,
@@ -16,8 +16,8 @@ import {
16
16
  pipe,
17
17
  lp,
18
18
  map
19
- } from './utils'
20
- import { createDelegatedRoutingV1HttpApiClient } from '@helia/delegated-routing-v1-http-api-client'
19
+ } from './utils.js'
20
+ import { delegatedRoutingV1HttpApiClient } from '@helia/delegated-routing-v1-http-api-client'
21
21
  import { createLibp2p } from 'libp2p'
22
22
  import { IDBDatastore } from 'datastore-idb'
23
23
  import { webTransport } from '@libp2p/webtransport'
@@ -28,13 +28,18 @@ import { noise } from '@chainsafe/libp2p-noise'
28
28
  import { yamux } from '@chainsafe/libp2p-yamux'
29
29
  import { pubsubPeerDiscovery } from '@libp2p/pubsub-peer-discovery'
30
30
  import { circuitRelayTransport } from '@libp2p/circuit-relay-v2'
31
- import { gossipsub } from '@chainsafe/libp2p-gossipsub'
31
+ import { gossipsub } from '@libp2p/gossipsub'
32
32
  import { identify, identifyPush } from '@libp2p/identify'
33
33
  import { peerIdFromString } from '@libp2p/peer-id'
34
34
  import { kadDHT, removePrivateAddressesMapper } from '@libp2p/kad-dht'
35
35
  import { simpleMetrics } from '@libp2p/simple-metrics'
36
+ import { ping } from '@libp2p/ping';
37
+ import { defaultLogger } from '@libp2p/logger';
38
+ import {createSignalingServer} from 'signalingserver.js';
36
39
 
37
-
40
+ /**************************************************************************
41
+ * Main class
42
+ **************************************************************************/
38
43
  class webpeerjs{
39
44
 
40
45
  //libp2p instance
@@ -108,16 +113,13 @@ class webpeerjs{
108
113
  //callback to websocket dialable
109
114
  #onWebsocketFn
110
115
 
111
- //time tracker for sending message
112
- #sendMessageTimeTracker
113
-
114
116
  id
115
117
  status
116
118
  IPFS
117
119
  address
118
120
  peers
119
121
 
120
- constructor(libp2p,dbstore,onMetrics,onWebsocketFn,onDialFn){
122
+ constructor(signalingserver,libp2p,dbstore,onMetrics,onWebsocketFn,onDialFn){
121
123
 
122
124
  this.#libp2p = libp2p
123
125
  this.#dbstore = dbstore
@@ -127,7 +129,7 @@ class webpeerjs{
127
129
  this.#webPeersId = []
128
130
  this.#webPeersAddrs = new Map()
129
131
  this.#dialedGoodPeers = new Map()
130
- this.#isDialWebsocket = false
132
+ this.#isDialWebsocket = false;
131
133
  this.#dialedKnownBootstrap = new Map()
132
134
  //this.#dialedDiscoveredPeers = []
133
135
  this.address = []
@@ -145,7 +147,6 @@ class webpeerjs{
145
147
  this.#lastTimeReceiveData = new Date().getTime()
146
148
  this.#onConnectQueue = []
147
149
  this.#msgTimeTracker = new Map()
148
- this.#sendMessageTimeTracker = 0
149
150
 
150
151
  this.peers = (function(f) {
151
152
  return f
@@ -155,7 +156,7 @@ class webpeerjs{
155
156
  return libp2p.status
156
157
  })(this.#libp2p);
157
158
 
158
- this.status = 'unconnected'
159
+ this.status = 'disconnected'
159
160
 
160
161
  this.IPFS = (function(libp2p,discoveredPeers) {
161
162
  const obj = {libp2p,discoveredPeers}
@@ -170,9 +171,43 @@ class webpeerjs{
170
171
 
171
172
  for(const topic of config.CONFIG_PUBSUB_PEER_DISCOVERY_HYBRID){
172
173
  this.#libp2p.services.pubsub.subscribe(topic)
173
- }
174
+ }
175
+
176
+
177
+ /**************************************************************************
178
+ * Signaling server
179
+ **************************************************************************/
180
+ signalingserver.data((signal,signal_id)=>{
181
+ if(!this.#connections.has(signal.id)){
182
+ let mddrs = []
183
+ for(const addr of signal.address){
184
+ if(!addr.includes('webrtc'))continue
185
+ const mddr = multiaddr(addr)
186
+ mddrs.push(mddr)
187
+ }
188
+ this.#dialMultiaddress(mddrs)
189
+ }
190
+ })
191
+
192
+ const broadcast = {
193
+ id : this.id,
194
+ address : this.address
195
+ }
196
+ signalingserver.send(broadcast);
197
+
198
+ setInterval(()=>{
199
+ const broadcast = {
200
+ id : this.id,
201
+ address : this.address
202
+ }
203
+ signalingserver.send(broadcast);
204
+ },15*1000)
205
+
174
206
 
175
- //listen to peer connect event
207
+
208
+ /**************************************************************************
209
+ * Listen on incoming connection
210
+ **************************************************************************/
176
211
  this.#libp2p.addEventListener("peer:connect",async (evt) => {
177
212
 
178
213
  //const connection = evt.detail;
@@ -240,7 +275,10 @@ class webpeerjs{
240
275
  });
241
276
 
242
277
 
243
- //listen message from subscribed pupsub topic
278
+
279
+ /**************************************************************************
280
+ * Listen message from subscribed pupsub topic
281
+ **************************************************************************/
244
282
  this.#libp2p.services.pubsub.addEventListener('message', event => {
245
283
 
246
284
  //console.log('on:'+event.detail.topic,event.detail.data)
@@ -410,13 +448,14 @@ class webpeerjs{
410
448
 
411
449
  //inbound message
412
450
  //use #msgIdtracker to prevent double message
413
- //use #msgTimeTracker to limit inbound message 1msg/s
451
+ //use #msgTimeTracker to limit inbound message count /s
414
452
  if(message){
415
453
  const msgID = msgId+id
416
454
  let oldmsgtime = 0
417
455
  let newmsgtime = new Date().getTime()
418
456
  if(this.#msgTimeTracker.has(id))oldmsgtime = this.#msgTimeTracker.get(id)
419
- const msgtimelimit = 1000
457
+ //const msgtimelimit = 1000
458
+ const msgtimelimit = -1
420
459
  if(!this.#msgIdtracker.has(msgID) && newmsgtime-oldmsgtime>msgtimelimit){
421
460
  this.#msgIdtracker.set(msgID,newmsgtime)
422
461
  this.#msgTimeTracker.set(id,newmsgtime)
@@ -484,7 +523,10 @@ class webpeerjs{
484
523
  })
485
524
 
486
525
 
487
- //listen to peer discovery event
526
+
527
+ /**************************************************************************
528
+ * Listen to peer discovery event
529
+ **************************************************************************/
488
530
  this.#libp2p.addEventListener('peer:discovery', (evt) => {
489
531
 
490
532
  //console.log('Discovered:', evt.detail.id.toString())
@@ -535,7 +577,10 @@ class webpeerjs{
535
577
  })
536
578
 
537
579
 
538
- //listen to peer disconnect event
580
+
581
+ /**************************************************************************
582
+ * Listen to peer disconnect event
583
+ **************************************************************************/
539
584
  this.#libp2p.addEventListener("peer:disconnect",async (evt) => {
540
585
 
541
586
  //const connection = evt.detail;
@@ -610,10 +655,16 @@ class webpeerjs{
610
655
  });
611
656
 
612
657
 
613
- //listen to self peer update
658
+
659
+ /**************************************************************************
660
+ * Listen to listen address change
661
+ **************************************************************************/
614
662
  this.#libp2p.addEventListener('self:peer:update', ({ detail: { peer } }) => {
663
+
664
+ //console.log('peer',peer)
615
665
  //const multiaddrs = peer.addresses.map(({ multiaddr }) => multiaddr)
616
666
  //console.log(`changed multiaddrs: peer ${peer.id.toString()} multiaddrs: ${multiaddrs}`)
667
+
617
668
  const id = peer.id.toString()
618
669
  const addrs = []
619
670
  peer.addresses.forEach((address)=>{
@@ -627,8 +678,22 @@ class webpeerjs{
627
678
  this.address = addrs
628
679
  this.#ping()
629
680
  this.#peerDiscoveryHybrid()
681
+ if(addrs.length > 0){
682
+ const broadcast = {
683
+ id : this.id,
684
+ address : this.address
685
+ }
686
+ signalingserver.send(broadcast);
687
+ this.status = 'connected'
688
+ }else{
689
+ this.status = 'disconnected'
690
+ }
630
691
  })
631
692
 
693
+
694
+ /**************************************************************************
695
+ * Listen on identity service
696
+ **************************************************************************/
632
697
  this.#libp2p.addEventListener('peer:identify', async (evt) => {
633
698
  //console.log('peer:identify '+evt.detail.peerId.toString(),evt.detail)
634
699
 
@@ -672,10 +737,9 @@ class webpeerjs{
672
737
  //reset this last seen
673
738
  const now = new Date().getTime()
674
739
  const metadata = {addrs:address,last:now}
675
- this.#connectedPeers.set(id,metadata)
740
+ this.#connectedPeers.set(id,metadata);
676
741
  }
677
742
 
678
-
679
743
  const command = 'peer-exchange'
680
744
  this.#dialProtocol(id,command)
681
745
 
@@ -757,8 +821,10 @@ class webpeerjs{
757
821
  },30e3)*/
758
822
 
759
823
  }
760
-
761
-
824
+
825
+ //this.#getAddress = (function(address) {
826
+ ///return this.address
827
+ //})(this.address);
762
828
 
763
829
 
764
830
  /*
@@ -776,17 +842,17 @@ class webpeerjs{
776
842
 
777
843
  joinRoom = room => {
778
844
  if (this.#rooms[room]) {
779
- return [
780
- this.#rooms[room].sendMessage,
781
- this.#rooms[room].listenMessage,
782
- this.#rooms[room].onMembersChange
783
- ]
845
+ return {
846
+ sendMessage : this.#rooms[room].sendMessage,
847
+ onMessage : this.#rooms[room].listenMessage,
848
+ onMembersChange : this.#rooms[room].onMembersChange
849
+ }
784
850
 
785
851
 
786
852
  }
787
853
 
788
854
  if (!room) {
789
- throw mkErr('room is required')
855
+ throw mkErr('Room name is required')
790
856
  }
791
857
 
792
858
  //join room version 1 user pupsub via pupsub peer discovery
@@ -805,17 +871,12 @@ class webpeerjs{
805
871
  onMessage : () => {},
806
872
  listenMessage : f => (this.#rooms[room] = {...this.#rooms[room], onMessage: f}),
807
873
  sendMessage : async (message) => {
808
- const now = (new Date()).getTime()
809
- if(now-this.#sendMessageTimeTracker < 1000){
810
- throw mkErr('can not send more than 1 message/s')
811
- }
812
- this.#sendMessageTimeTracker = now
813
- const msgId = (new Date()).getTime()
874
+ const msgId = crypto.randomUUID();
814
875
  const data = JSON.stringify({prefix:config.CONFIG_PREFIX,room,message,id:this.#libp2p.peerId.toString(),msgId})
815
876
  const arr = uint8ArrayFromString(data)
816
877
  const sizelimit = config.CONFIG_MESSAGE_SIZE_LIMIT
817
878
  if(arr.byteLength > sizelimit){
818
- throw mkErr('message too large')
879
+ throw mkErr(`Only message less than ${sizelimit} byte allowed`);
819
880
  }
820
881
  const peer = {
821
882
  publicKey: this.#libp2p.peerId.publicKey,
@@ -832,11 +893,11 @@ class webpeerjs{
832
893
  }
833
894
  }
834
895
 
835
- return [
836
- this.#rooms[room].sendMessage,
837
- this.#rooms[room].listenMessage,
838
- this.#rooms[room].onMembersChange
839
- ]
896
+ return {
897
+ sendMessage : this.#rooms[room].sendMessage,
898
+ onMessage : this.#rooms[room].listenMessage,
899
+ onMembersChange : this.#rooms[room].onMembersChange
900
+ }
840
901
  }
841
902
 
842
903
  dial(addr){
@@ -922,18 +983,20 @@ class webpeerjs{
922
983
  const item = {id:peer[0],address:peer[1].addrs}
923
984
  this.#connectedPeersArr.push(item)
924
985
  }
925
- if(this.#connectedPeers.size > 0){
926
- this.status = 'connected'
927
- }
928
- else{
929
- this.status = 'unconnected'
930
- }
931
986
  this.#ping()
932
987
  }
933
-
988
+
989
+
990
+
991
+ /**************************************************************************
992
+ * Handle custom protocol
993
+ **************************************************************************/
934
994
  async #registerProtocol(){
935
995
 
936
996
  const handler = async ({ connection, stream }) => {
997
+
998
+ //console.log('onprotocol',connection);
999
+
937
1000
  try{
938
1001
  const output = await pipe(
939
1002
  stream.source,
@@ -1021,7 +1084,7 @@ class webpeerjs{
1021
1084
  await this.#libp2p.handle(config.CONFIG_PROTOCOL, handler, {
1022
1085
  maxInboundStreams: 100,
1023
1086
  maxOutboundStreams: 100,
1024
- runOnTransientConnection:config.CONFIG_RUN_ON_TRANSIENT_CONNECTION
1087
+ runOnLimitedConnection:config.CONFIG_RUN_ON_TRANSIENT_CONNECTION
1025
1088
  })
1026
1089
 
1027
1090
  await this.#libp2p.register(config.CONFIG_PROTOCOL, {
@@ -1036,7 +1099,11 @@ class webpeerjs{
1036
1099
  })
1037
1100
 
1038
1101
  }
1039
-
1102
+
1103
+
1104
+ /**************************************************************************
1105
+ * Dial custom protocol
1106
+ **************************************************************************/
1040
1107
  async #dialProtocol(id,command){
1041
1108
 
1042
1109
  const connections = this.#libp2p.getConnections().map((con)=>{return {id:con.remotePeer.toString(),addr:con.remoteAddr.toString()}})
@@ -1068,7 +1135,7 @@ class webpeerjs{
1068
1135
 
1069
1136
  try{
1070
1137
 
1071
- const stream = await this.#libp2p.dialProtocol(mddr, config.CONFIG_PROTOCOL,{runOnTransientConnection:config.CONFIG_RUN_ON_TRANSIENT_CONNECTION})
1138
+ const stream = await this.#libp2p.dialProtocol(mddr, config.CONFIG_PROTOCOL,{runOnLimitedConnection:config.CONFIG_RUN_ON_TRANSIENT_CONNECTION})
1072
1139
 
1073
1140
  const output = await pipe(
1074
1141
  message,
@@ -1127,42 +1194,6 @@ class webpeerjs{
1127
1194
  }
1128
1195
  }
1129
1196
 
1130
- async #findHybridPeer(){
1131
-
1132
- if(!navigator.onLine)return
1133
- if(!this.#isDialEnabled)return
1134
- if(this.#connectedPeers.size > 5)return
1135
-
1136
- for(const target of config.CONFIG_KNOWN_BOOTSTRAP_HYBRID_IDS){
1137
- if(!this.#isConnected(target) && !this.#connections.has(target)){
1138
- //console.log('findPeer',target)
1139
- const peerId = peerIdFromString(target)
1140
- //const peerInfo = await this.#libp2p.services.aminoDHT.findPeer(peerId)
1141
-
1142
- //console.info(peerInfo)
1143
- for await (const event of this.#libp2p.services.aminoDHT.findPeer(peerId)){
1144
- //console.info('findPeer',event)
1145
- if (event.name === 'FINAL_PEER'){
1146
- //console.log(event.peer.id.toString(),event.peer.multiaddrs.toString())
1147
- let mddrs = []
1148
- let addrs = []
1149
- const id = event.peer.id.toString()
1150
- for(const mddr of event.peer.multiaddrs){
1151
- const peeraddr = mddr.toString()+'/p2p/'+id
1152
- const peermddr = multiaddr(peeraddr)
1153
- addrs.push(peeraddr)
1154
- mddrs.push(peermddr)
1155
- }
1156
- this.#dialedKnownBootstrap.set(id,addrs)
1157
- if(!this.#isConnected(id)){
1158
- this.#dialMultiaddress(mddrs)
1159
- }
1160
- }
1161
- }
1162
- }
1163
- }
1164
- }
1165
-
1166
1197
 
1167
1198
  //check the last seen in web peer
1168
1199
  #trackLastSeen(){
@@ -1597,6 +1628,45 @@ class webpeerjs{
1597
1628
  },5000)
1598
1629
  }
1599
1630
 
1631
+ async #findHybridPeer(){
1632
+
1633
+ this.#dialKnownID();
1634
+ return;
1635
+
1636
+ if(!navigator.onLine)return
1637
+ if(!this.#isDialEnabled)return
1638
+ if(this.#connectedPeers.size > 5)return
1639
+
1640
+ for(const target of config.CONFIG_KNOWN_BOOTSTRAP_HYBRID_IDS){
1641
+ if(!this.#isConnected(target) && !this.#connections.has(target)){
1642
+ //console.log('findPeer',target)
1643
+ const peerId = peerIdFromString(target)
1644
+ //const peerInfo = await this.#libp2p.services.aminoDHT.findPeer(peerId)
1645
+
1646
+ //console.info(peerInfo)
1647
+ for await (const event of this.#libp2p.services.aminoDHT.findPeer(peerId)){
1648
+ //console.info('findPeer',event)
1649
+ if (event.name === 'FINAL_PEER'){
1650
+ //console.log(event.peer.id.toString(),event.peer.multiaddrs.toString())
1651
+ let mddrs = []
1652
+ let addrs = []
1653
+ const id = event.peer.id.toString()
1654
+ for(const mddr of event.peer.multiaddrs){
1655
+ const peeraddr = mddr.toString()+'/p2p/'+id
1656
+ const peermddr = multiaddr(peeraddr)
1657
+ addrs.push(peeraddr)
1658
+ mddrs.push(peermddr)
1659
+ }
1660
+ this.#dialedKnownBootstrap.set(id,addrs)
1661
+ if(!this.#isConnected(id)){
1662
+ this.#dialMultiaddress(mddrs)
1663
+ }
1664
+ }
1665
+ }
1666
+ }
1667
+ }
1668
+ }
1669
+
1600
1670
  async #dialSavedKnownID(){
1601
1671
 
1602
1672
  if(!navigator.onLine)return
@@ -1622,7 +1692,7 @@ class webpeerjs{
1622
1692
  if(firsttime){
1623
1693
  for(const target of config.CONFIG_KNOWN_BOOTSTRAP_PEERS_IDS){
1624
1694
  const api = config.CONFIG_DELEGATED_API
1625
- const delegatedClient = createDelegatedRoutingV1HttpApiClient(api)
1695
+ const delegatedClient = delegatedRoutingV1HttpApiClient({url:api})({logger: defaultLogger()})
1626
1696
  const peer = await first(delegatedClient.getPeers(peerIdFromString(target)))
1627
1697
  if(!peer)continue
1628
1698
  const address = peer.Addrs
@@ -1657,7 +1727,7 @@ class webpeerjs{
1657
1727
  if(!this.#connections.has(target) && (this.#dbstoreData.has(target) || firsttime)){
1658
1728
  //console.log('#dialUpdateSavedKnownID()',target)
1659
1729
  const api = config.CONFIG_DELEGATED_API
1660
- const delegatedClient = createDelegatedRoutingV1HttpApiClient(api)
1730
+ const delegatedClient = delegatedRoutingV1HttpApiClient({url:api})({logger: defaultLogger()})
1661
1731
  const peer = await first(delegatedClient.getPeers(peerIdFromString(target)))
1662
1732
  if(!peer){
1663
1733
  if (navigator.onLine) {
@@ -1693,7 +1763,7 @@ class webpeerjs{
1693
1763
 
1694
1764
  //console.log('#dialKnownID()')
1695
1765
  const api = config.CONFIG_DELEGATED_API
1696
- const delegatedClient = createDelegatedRoutingV1HttpApiClient(api)
1766
+ const delegatedClient = delegatedRoutingV1HttpApiClient({url:api})({logger: defaultLogger()})
1697
1767
  const BOOTSTRAP_PEER_IDS = config.CONFIG_KNOWN_BOOTSTRAP_PEERS_IDS
1698
1768
  const peers = await Promise.all(
1699
1769
  BOOTSTRAP_PEER_IDS.map((peerId) => first(delegatedClient.getPeers(peerIdFromString(peerId)))),
@@ -1766,7 +1836,7 @@ class webpeerjs{
1766
1836
  BOOTSTRAP_PEER_IDS.push(id)
1767
1837
  }
1768
1838
  const api = config.CONFIG_DELEGATED_API
1769
- const delegatedClient = createDelegatedRoutingV1HttpApiClient(api)
1839
+ const delegatedClient = delegatedRoutingV1HttpApiClient({url:api})({logger: defaultLogger()})
1770
1840
  const peers = await Promise.all(
1771
1841
  BOOTSTRAP_PEER_IDS.map((peerId) => first(delegatedClient.getPeers(peerIdFromString(peerId)))),
1772
1842
  )
@@ -1845,7 +1915,7 @@ class webpeerjs{
1845
1915
 
1846
1916
  //dial only webtransport multiaddrs
1847
1917
  async #dialWebtransport(multiaddrs){
1848
- const webTransportMadrs = multiaddrs.filter((maddr) => maddr.protoNames().includes('webtransport')&&maddr.protoNames().includes('certhash'))
1918
+ const webTransportMadrs = multiaddrs.filter((maddr) => maddr.toString().includes('webtransport')&&maddr.toString().includes('certhash'))
1849
1919
  for (const mddr of webTransportMadrs) {
1850
1920
  try {
1851
1921
  //console.log(`attempting to dial webtransport multiaddr: %o`, mddr.toString())
@@ -1860,7 +1930,7 @@ class webpeerjs{
1860
1930
 
1861
1931
  //dial only websocket multiaddrs
1862
1932
  async #dialWebsocket(multiaddrs){
1863
- const webSocketMadrs = multiaddrs.filter((maddr) => maddr.protoNames().includes('wss'))
1933
+ const webSocketMadrs = multiaddrs.filter((maddr) => maddr.toString().includes('wss'))
1864
1934
  for (const mddr of webSocketMadrs) {
1865
1935
  try {
1866
1936
  //console.log(`attempting to dial websocket multiaddr: %o`, mddr)
@@ -1872,293 +1942,183 @@ class webpeerjs{
1872
1942
  }
1873
1943
  }
1874
1944
  }
1875
-
1876
-
1877
- //entry point to webpeerjs
1878
- static async createWebpeer(){
1879
-
1880
- // all libp2p debug logs
1881
- //localStorage.setItem('debug', 'libp2p:*')
1882
-
1883
- const dbstore = new IDBDatastore(config.CONFIG_DBSTORE_PATH)
1884
- await dbstore.open()
1885
-
1886
- const bootstrapAddrs = []
1887
-
1888
- //let addrs = []
1889
- const getbootstrap = config.CONFIG_KNOWN_BOOTSTRAP_PEERS_ADDRS
1890
- for(const peer of getbootstrap){
1891
- const addrs = peer.Peers[0].Addrs
1892
- const id = peer.Peers[0].ID
1893
- //let mddrs = []
1894
- for(const addr of addrs){
1895
- if(addr.includes('webtransport')&&addr.includes('certhash')){
1896
- bootstrapAddrs.push(addr+'/p2p/'+id)
1897
- }
1898
- }
1899
- }
1900
-
1901
- let onMetricsFn = () => {}
1902
- const onMetrics = f => (onMetricsFn = f)
1903
-
1904
- let isWebsocket = false
1905
- let onWebsocketFn = () => {}
1906
- const onWebsocket = f => (onWebsocketFn = f)
1907
- onWebsocket((data)=>{
1908
- isWebsocket = data
1909
- })
1910
-
1911
- let isDial = true
1912
- let onDialFn = () => {}
1913
- const onDial = f => (onDialFn = f)
1914
- onDial((data)=>{
1915
- //if(isDial!=data)console.warn('isDial',data)
1916
- isDial = data
1917
- })
1918
-
1919
- let listenaddress = []
1920
-
1921
- if(config.CONFIG_RUN_ON_TRANSIENT_CONNECTION == false){
1922
- listenaddress.push('/webrtc')
1923
- }
1924
-
1925
- const stunurls = config.CONFIG_WEBRTC_STUN_URLS
1926
- const stunurlsbackup = config.CONFIG_WEBRTC_STUN_URLS_BACKUP
1927
-
1928
- const turnurls = atob(config.CONFIG_WEBRTC_TURN_HOST)
1929
- const turnusername = atob(config.CONFIG_WEBRTC_TURN_USER)
1930
- const turncredential = atob(config.CONFIG_WEBRTC_TURN_PWD)
1931
-
1932
- const turnurlsbackup = atob(config.CONFIG_WEBRTC_TURN_HOST_BACKUP)
1933
- const turnusernamebackup = atob(config.CONFIG_WEBRTC_TURN_USER_BACKUP)
1934
- const turncredentialbackup = atob(config.CONFIG_WEBRTC_TURN_PWD_BACKUP)
1935
-
1936
- async function checkice(stunurls,turnurls,turnusername,turncredential,time){
1937
- return new Promise((resolve)=>{
1938
-
1939
- let stun = false
1940
- let turn = false
1941
-
1942
- const timeout = setTimeout(()=>{
1943
- let ice = []
1944
- ice.push(stun)
1945
- ice.push(turn)
1946
- resolve(ice)
1947
- },time)
1948
-
1949
- function check(){
1950
- if(stun && turn){
1951
- let ice = []
1952
- ice.push(stun)
1953
- ice.push(turn)
1954
- clearTimeout(timeout)
1955
- resolve(ice)
1956
- }
1957
- }
1958
-
1959
- //test ice servers
1960
-
1961
- const iceServers = [
1962
- {
1963
- urls: stunurls
1964
- },
1965
- {
1966
- urls: turnurls,
1967
- username: turnusername,
1968
- credential: turncredential
1969
- }
1970
- ];
1971
1945
 
1972
- const pc = new RTCPeerConnection({
1973
- iceServers
1974
- });
1975
-
1976
- pc.onicecandidate = (e) => {
1977
- if (!e.candidate) return;
1946
+ }
1978
1947
 
1979
- //console.log(e.candidate.candidate);
1980
1948
 
1981
- // stun works
1982
- if(e.candidate.type == "srflx"){
1983
- //console.log('publicip',e.candidate.address);
1984
- stun = {
1985
- urls: stunurls
1986
- }
1987
- check()
1988
- }
1989
-
1990
- // turn works
1991
- if(e.candidate.type == "relay"){
1992
- turn = {
1993
- urls: turnurls,
1994
- username: turnusername,
1995
- credential: turncredential
1996
- }
1997
- check()
1998
- }
1999
- };
1949
+ /**************************************************************************
1950
+ * Entry point to create a new peer
1951
+ **************************************************************************/
1952
+ const createWebPEER = async (configuration) => {
2000
1953
 
2001
- pc.onicecandidateerror = (e) => {
2002
- console.debug(e);
2003
- };
2004
-
2005
- pc.createDataChannel('webpeerjs');
2006
- pc.createOffer().then(offer => pc.setLocalDescription(offer));
2007
- })
2008
- }
2009
-
2010
- let ice = []
2011
-
2012
- let configuration = {}
2013
-
2014
- if(arguments.length > 0){
2015
- configuration = arguments[0]
1954
+ // all libp2p debug logs
1955
+ if(config.CONFIG_DEBUG_ENABLED){
1956
+ localStorage.setItem('debug', 'libp2p:*');
1957
+ }
1958
+
1959
+ let signalconfig = {};
1960
+ if(configuration && configuration.networkName){
1961
+ signalconfig['appid'] = configuration.networkName;
1962
+ }else{
1963
+ signalconfig['appid'] = config.CONFIG_PREFIX;
1964
+ }
1965
+
1966
+ const signalingserver = createSignalingServer(signalconfig);
1967
+
1968
+ const dbstore = new IDBDatastore(config.CONFIG_DBSTORE_PATH)
1969
+ await dbstore.open()
1970
+
1971
+ const bootstrapAddrs = []
1972
+
1973
+ //let addrs = []
1974
+ const getbootstrap = config.CONFIG_KNOWN_BOOTSTRAP_PEERS_ADDRS
1975
+ for(const peer of getbootstrap){
1976
+ const addrs = peer.Peers[0].Addrs
1977
+ const id = peer.Peers[0].ID
1978
+ //let mddrs = []
1979
+ for(const addr of addrs){
1980
+ if(addr.includes('webtransport')&&addr.includes('certhash')){
1981
+ bootstrapAddrs.push(addr+'/p2p/'+id)
1982
+ }
2016
1983
  }
2017
-
2018
- //set rtc configuration
2019
- if(configuration.rtcConfiguration === undefined){
2020
-
2021
- ice = await checkice(stunurls,turnurls,turnusername,turncredential,5000)
1984
+ }
2022
1985
 
2023
- //console.log(ice)
2024
-
2025
- //recheck ice
2026
- if(!ice[0] && !ice[1]){
2027
- ice = await checkice(stunurlsbackup,turnurlsbackup,turnusernamebackup,turncredentialbackup,5000)
2028
- }else if (ice[0] && !ice[1]){
2029
- ice = await checkice(stunurls,turnurlsbackup,turnusernamebackup,turncredentialbackup,5000)
2030
- }else if (!ice[0] && ice[1]){
2031
- ice = await checkice(stunurlsbackup,turnurls,turnusername,turncredential,5000)
2032
- }
2033
-
2034
- //console.log(ice)
2035
-
2036
- //final ice remove false value
2037
- ice.forEach(function(value, index) {
2038
- if(!value){
2039
- this.splice(index, 1)
2040
- }
2041
- }, ice);
2042
-
2043
- //console.log(ice)
1986
+ let onMetricsFn = () => {}
1987
+ const onMetrics = f => (onMetricsFn = f)
1988
+
1989
+ let isWebsocket = false
1990
+ let onWebsocketFn = () => {}
1991
+ const onWebsocket = f => (onWebsocketFn = f)
1992
+ onWebsocket((data)=>{
1993
+ isWebsocket = data
1994
+ })
1995
+
1996
+ let isDial = true
1997
+ let onDialFn = () => {}
1998
+ const onDial = f => (onDialFn = f)
1999
+ onDial((data)=>{
2000
+ //if(isDial!=data)console.warn('isDial',data)
2001
+ isDial = data
2002
+ })
2003
+
2004
+ let listenaddress = ['/p2p-circuit']
2005
+
2006
+ if(config.CONFIG_RUN_ON_TRANSIENT_CONNECTION == false){
2007
+ listenaddress.push('/webrtc')
2008
+ }
2009
+
2010
+ let webrtcconfig = {}
2044
2011
 
2045
- configuration.rtcConfiguration = {
2046
- iceServers: ice,
2047
- }
2048
- }
2049
-
2050
-
2051
- //create libp2p instance
2052
- const libp2p = await createLibp2p({
2053
- addresses: {
2054
- listen: listenaddress,
2055
- },
2056
- transports:[
2057
- webTransport(),
2058
- webSockets(),
2059
- webRTC({
2060
- rtcConfiguration: configuration.rtcConfiguration,
2061
- }),
2062
- circuitRelayTransport({
2063
- discoverRelays: config.CONFIG_DISCOVER_RELAYS,
2064
- reservationConcurrency: 1,
2065
- maxReservationQueueLength: 3
2066
- }),
2067
- ],
2068
- connectionManager: {
2069
- maxConnections: config.CONFIG_MAX_CONNECTIONS,
2070
- minConnections: config.CONFIG_MIN_CONNECTIONS,
2071
- autoDialInterval:60e3,
2072
- autoDialConcurrency:0,
2073
- autoDialMaxQueueLength:0,
2074
- autoDialPriority:1000,
2075
- autoDialDiscoveredPeersDebounce:60e3,
2076
- maxParallelDials: 3,
2077
- dialTimeout: 5e3,
2078
- maxIncomingPendingConnections: 5,
2079
- maxDialQueueLength:10,
2080
- inboundConnectionThreshold:3,
2081
- maxPeerAddrsToDial:2,
2082
- inboundUpgradeTimeout:5e3
2083
- },
2084
- connectionEncryption: [noise()],
2085
- streamMuxers: [
2086
- yamux({
2087
- maxInboundStreams: 100,
2088
- maxOutboundStreams: 100,
2089
- })
2090
- ],
2091
- connectionGater: {
2092
- filterMultiaddrForPeer: async (peer, multiaddrTest) => {
2093
- const multiaddrString = multiaddrTest.toString()
2094
- if (
2095
- multiaddrString.includes("/ip4/127.0.0.1") ||
2096
- multiaddrString.includes("/ip6/")
2097
- ) {
2098
- return false
2099
- }
2100
- if(multiaddrString.includes("/ws/") || multiaddrString.includes("/wss/"))return isWebsocket
2101
- return isDial
2102
- },
2103
- denyDialMultiaddr: async (multiaddrTest) => {
2104
- const multiaddrString = multiaddrTest.toString()
2105
- if (
2106
- multiaddrString.includes("/ip4/127.0.0.1") ||
2107
- multiaddrString.includes("/ip6/")
2108
- ) {
2109
- return true
2110
- }
2111
- if(multiaddrString.includes("/ws/") || multiaddrString.includes("/wss/"))return !isWebsocket
2112
- return !isDial
2113
- },
2114
- },
2115
- peerDiscovery: [
2116
- pubsubPeerDiscovery({
2117
- interval: 5_000,
2118
- topics: config.CONFIG_PUBSUB_PEER_DISCOVERY_WEBPEER,
2119
- listenOnly: false,
2120
- }),
2121
-
2122
- ],
2123
- services: {
2124
- pubsub: gossipsub({
2125
- allowPublishToZeroTopicPeers: true,
2126
- msgIdFn: msgIdFnStrictNoSign,
2127
- ignoreDuplicatePublishError: true,
2128
- runOnTransientConnection:config.CONFIG_RUN_ON_TRANSIENT_CONNECTION,
2129
- }),
2130
- identify: identify(),
2131
- identifyPush: identifyPush(),
2132
- aminoDHT: kadDHT({
2133
- protocol: '/ipfs/kad/1.0.0',
2134
- peerInfoMapper: removePrivateAddressesMapper,
2135
- clientMode: false
2136
- }),
2137
- dcutr: dcutr()
2012
+ if(configuration && configuration.rtcConfiguration){
2013
+ webrtcconfig[rtcConfiguration] = configuration.rtcConfiguration
2014
+ }
2015
+
2016
+
2017
+ //create libp2p instance
2018
+ const libp2p = await createLibp2p({
2019
+ addresses: {
2020
+ listen: listenaddress,
2021
+ },
2022
+ transports:[
2023
+ webTransport(),
2024
+ webSockets(),
2025
+ webRTC(webrtcconfig),
2026
+ circuitRelayTransport({
2027
+ reservationConcurrency: config.CONFIG_DISCOVER_RELAYS
2028
+ }),
2029
+ ],
2030
+ connectionManager: {
2031
+ maxConnections: config.CONFIG_MAX_CONNECTIONS,
2032
+ minConnections: config.CONFIG_MIN_CONNECTIONS,
2033
+ autoDialInterval:60e3,
2034
+ autoDialConcurrency:0,
2035
+ autoDialMaxQueueLength:0,
2036
+ autoDialPriority:1000,
2037
+ autoDialDiscoveredPeersDebounce:60e3,
2038
+ maxParallelDials: 3,
2039
+ dialTimeout: 5e3,
2040
+ maxIncomingPendingConnections: 5,
2041
+ maxDialQueueLength:10,
2042
+ inboundConnectionThreshold:3,
2043
+ maxPeerAddrsToDial:2,
2044
+ inboundUpgradeTimeout:5e3
2045
+ },
2046
+ connectionEncrypters: [noise()],
2047
+ streamMuxers: [
2048
+ yamux({
2049
+ maxInboundStreams: 100,
2050
+ maxOutboundStreams: 100,
2051
+ })
2052
+ ],
2053
+ connectionGater: {
2054
+ filterMultiaddrForPeer: async (peer, multiaddrTest) => {
2055
+ const multiaddrString = multiaddrTest.toString()
2056
+ if (
2057
+ multiaddrString.includes("/ip4/127.0.0.1") ||
2058
+ multiaddrString.includes("/ip6/")
2059
+ ) {
2060
+ return false
2061
+ }
2062
+ if(multiaddrString.includes("/ws/") || multiaddrString.includes("/wss/"))return isWebsocket
2063
+ return isDial
2138
2064
  },
2139
- peerStore: {
2140
- persistence: true,
2141
- threshold: 1
2065
+ denyDialMultiaddr: async (multiaddrTest) => {
2066
+ const multiaddrString = multiaddrTest.toString()
2067
+ if (
2068
+ multiaddrString.includes("/ip4/127.0.0.1") ||
2069
+ multiaddrString.includes("/ip6/")
2070
+ ) {
2071
+ return true
2072
+ }
2073
+ if(multiaddrString.includes("/ws/") || multiaddrString.includes("/wss/"))return !isWebsocket
2074
+ return !isDial
2142
2075
  },
2143
- metrics: simpleMetrics({
2144
- onMetrics: (metrics) => {onMetricsFn(metrics)},
2145
- intervalMs: 1000
2146
- })
2076
+ },
2077
+ peerDiscovery: [
2078
+ pubsubPeerDiscovery({
2079
+ interval: 5_000,
2080
+ topics: config.CONFIG_PUBSUB_PEER_DISCOVERY_WEBPEER,
2081
+ listenOnly: false,
2082
+ }),
2083
+
2084
+ ],
2085
+ services: {
2086
+ pubsub: gossipsub({
2087
+ allowPublishToZeroTopicPeers: true,
2088
+ msgIdFn: msgIdFnStrictNoSign,
2089
+ ignoreDuplicatePublishError: true,
2090
+ runOnLimitedConnection:config.CONFIG_RUN_ON_TRANSIENT_CONNECTION,
2091
+ }),
2092
+ identify: identify(),
2093
+ ping: ping(),
2094
+ identifyPush: identifyPush(),
2095
+ aminoDHT: kadDHT({
2096
+ protocol: '/ipfs/kad/1.0.0',
2097
+ peerInfoMapper: removePrivateAddressesMapper,
2098
+ clientMode: false
2099
+ }),
2100
+ dcutr: dcutr()
2101
+ },
2102
+ peerStore: {
2103
+ persistence: true,
2104
+ threshold: 1
2105
+ },
2106
+ metrics: simpleMetrics({
2107
+ onMetrics: (metrics) => {onMetricsFn(metrics)},
2108
+ intervalMs: 1000
2147
2109
  })
2148
-
2149
-
2150
-
2151
- //console.log(`Node started with id ${libp2p.peerId.toString()}`)
2110
+ })
2111
+
2112
+ //console.log(`Node started with id ${libp2p.peerId.toString()}`)
2152
2113
 
2153
- //DHT server mode act as bootstrap peer in IPFS network
2154
- await libp2p.services.aminoDHT.setMode("server")
2155
-
2156
-
2157
- //return webpeerjs class
2158
- return new webpeerjs(libp2p,dbstore,onMetrics,onWebsocketFn,onDialFn)
2159
- }
2114
+ //DHT server mode act as bootstrap peer in IPFS network
2115
+ await libp2p.services.aminoDHT.setMode("server")
2116
+
2117
+
2118
+ //return webpeerjs class
2119
+ return new webpeerjs(signalingserver,libp2p,dbstore,onMetrics,onWebsocketFn,onDialFn)
2160
2120
  }
2161
2121
 
2162
2122
 
2163
2123
  //export module
2164
- export {webpeerjs}
2124
+ export {createWebPEER}