webpeerjs 0.1.7 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webpeerjs",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "WebPEER.js is decentralized P2P JS library for communication between applications in browser.",
5
5
  "main": "./dist/umd/webpeerjs.js",
6
6
  "module": "./src/webpeerjs.js",
@@ -32,17 +32,17 @@
32
32
  "url": "git+https://github.com/nuzulul/webpeerjs.git"
33
33
  },
34
34
  "keywords": [
35
- "p2p",
35
+ "webpeer",
36
+ "p2p",
37
+ "p2p-network",
38
+ "webpeer-network",
36
39
  "ipfs",
37
40
  "libp2p",
38
41
  "peer",
39
42
  "peer-to-peer",
40
43
  "decentralized",
41
44
  "browser-to-browser",
42
- "dapp",
43
45
  "distributed",
44
- "decentralized-web",
45
- "distributed-web",
46
46
  "serverless"
47
47
  ],
48
48
  "author": {
package/src/config.js CHANGED
@@ -6,7 +6,7 @@ export const CONFIG_PROTOCOL = '/'+prefix+'/1.0.0'
6
6
  export const CONFIG_BLOCKSTORE_PATH = prefix+'-blockstore'
7
7
  export const CONFIG_DATASTORE_PATH = prefix+'-datastore'
8
8
  export const CONFIG_DBSTORE_PATH = prefix+'-dbstore'
9
- export const CONFIG_MAX_CONNECTIONS = 50
9
+ export const CONFIG_MAX_CONNECTIONS = 30
10
10
  export const CONFIG_MIN_CONNECTIONS = 0
11
11
  export const CONFIG_DISCOVER_RELAYS = 1
12
12
  export const CONFIG_PEER_DISCOVERY_UNIVERSAL_CONNECTIVITY = 'universal-connectivity-browser-peer-discovery'
package/src/utils.js CHANGED
@@ -121,6 +121,7 @@ let lastStats = {
121
121
  }
122
122
 
123
123
  let fail = 0
124
+ let lastfail = 0
124
125
  let isDialEnabled = true
125
126
  let lastfailtreshold = 0
126
127
  let isAutoDialEnabled = true
@@ -185,6 +186,20 @@ export function metrics(data){
185
186
 
186
187
  fail = errors+timeouts
187
188
  //const treshold = errors+timeouts+stats.open+stats.pending
189
+ //console.log('fail',fail)
190
+
191
+ //detect fail timeout, in chrome fail webtransport get reset after 5 minutes
192
+ if(lastfail>fail){
193
+ setTimeout(()=>{
194
+ if(isAutoDialEnabled){
195
+ lastfailtresholdauto = lastfailtresholdauto+(lastfail-fail)
196
+ }
197
+ if(isDialEnabled){
198
+ lastfailtreshold = lastfailtreshold+(lastfail-fail)
199
+ }
200
+ },5*60*1000)
201
+ }
202
+ lastfail = fail
188
203
 
189
204
  if ((fail-lastfailtreshold)>config.CONFIG_DIAL_MAX_ERROR_LIMIT){
190
205
  if(isDialEnabled){
package/src/webpeerjs.js CHANGED
@@ -92,6 +92,9 @@ class webpeerjs{
92
92
  //message tracker avoid double
93
93
  #msgIdtracker
94
94
 
95
+ //inbound message time tracker
96
+ #msgTimeTracker
97
+
95
98
  //map of peer exchange data
96
99
  #peerexchangedata
97
100
 
@@ -105,6 +108,9 @@ class webpeerjs{
105
108
  //callback to websocket dialable
106
109
  #onWebsocketFn
107
110
 
111
+ //time tracker for sending message
112
+ #sendMessageTimeTracker
113
+
108
114
  id
109
115
  status
110
116
  IPFS
@@ -133,11 +139,13 @@ class webpeerjs{
133
139
  this.#trackDisconnect = new Map()
134
140
  this.#dialQueue = []
135
141
  this.#isDialEnabled = true
136
- this.#msgIdtracker = []
142
+ this.#msgIdtracker = new Map()
137
143
  this.#peerexchangedata = new Map()
138
144
  this.#lastTimeConnectToNetwork = new Date().getTime()
139
145
  this.#lastTimeReceiveData = new Date().getTime()
140
146
  this.#onConnectQueue = []
147
+ this.#msgTimeTracker = new Map()
148
+ this.#sendMessageTimeTracker = 0
141
149
 
142
150
  this.peers = (function(f) {
143
151
  return f
@@ -209,18 +217,22 @@ class webpeerjs{
209
217
  let address = [addr]
210
218
 
211
219
  if(this.#connectedPeers.has(id)){
212
- //reset this last seen
213
- const now = new Date().getTime()
214
- const metadata = {addrs:address,last:now}
215
- this.#connectedPeers.set(id,metadata)
220
+ if(this.#lastTimeReceiveData < 10*1000){
221
+ //reset this last seen
222
+ const now = new Date().getTime()
223
+ const metadata = {addrs:address,last:now}
224
+ this.#connectedPeers.set(id,metadata)
225
+ }
216
226
  }
217
- else if(this.#lastTimeReceiveData < 10*1000){
218
- //add to connected webpeers
219
- this.#onConnectFnUpdate(id)
220
- const now = new Date().getTime()
221
- const metadata = {addrs:address,last:now}
222
- this.#connectedPeers.set(id,metadata)
223
- this.#updatePeers()
227
+ else {
228
+ if(this.#lastTimeReceiveData < 10*1000){
229
+ //add to connected webpeers
230
+ this.#onConnectFnUpdate(id)
231
+ const now = new Date().getTime()
232
+ const metadata = {addrs:address,last:now}
233
+ this.#connectedPeers.set(id,metadata)
234
+ this.#updatePeers()
235
+ }
224
236
  }
225
237
 
226
238
  }
@@ -265,20 +277,24 @@ class webpeerjs{
265
277
  if(this.#webPeersId.includes(senderPeerId)){
266
278
 
267
279
  if(this.#connectedPeers.has(senderPeerId)){
268
- //reset this last seen
269
- const address = this.#connectedPeers.get(senderPeerId).addrs
270
- const now = new Date().getTime()
271
- const metadata = {addrs:address,last:now}
272
- this.#connectedPeers.set(senderPeerId,metadata)
280
+ if(this.#lastTimeReceiveData < 10*1000){
281
+ //reset this last seen
282
+ const address = this.#connectedPeers.get(senderPeerId).addrs
283
+ const now = new Date().getTime()
284
+ const metadata = {addrs:address,last:now}
285
+ this.#connectedPeers.set(senderPeerId,metadata)
286
+ }
273
287
  }
274
- else if(this.#lastTimeReceiveData < 10*1000){
275
- //add to connected webpeers
276
- this.#onConnectFnUpdate(senderPeerId)
277
- const address = this.#webPeersAddrs.get(senderPeerId)
278
- const now = new Date().getTime()
279
- const metadata = {addrs:address,last:now}
280
- this.#connectedPeers.set(senderPeerId,metadata)
281
- this.#updatePeers()
288
+ else {
289
+ if(this.#lastTimeReceiveData < 10*1000){
290
+ //add to connected webpeers
291
+ this.#onConnectFnUpdate(senderPeerId)
292
+ const address = this.#webPeersAddrs.get(senderPeerId)
293
+ const now = new Date().getTime()
294
+ const metadata = {addrs:address,last:now}
295
+ this.#connectedPeers.set(senderPeerId,metadata)
296
+ this.#updatePeers()
297
+ }
282
298
  }
283
299
 
284
300
  //dial if not connected
@@ -366,6 +382,13 @@ class webpeerjs{
366
382
  }
367
383
  this.#updatePeers()
368
384
  }else{
385
+ //reset this last seen
386
+ let addr = this.#connectedPeers.get(id).addrs
387
+ if(address)addr = address
388
+ const now = new Date().getTime()
389
+ const metadata = {addrs:addr,last:now}
390
+ this.#connectedPeers.set(id,metadata)
391
+ //update address
369
392
  if(address){
370
393
  if(address.length > 0){
371
394
  this.#webPeersAddrs.set(id,address)
@@ -386,10 +409,17 @@ class webpeerjs{
386
409
  }
387
410
 
388
411
  //inbound message
412
+ //use #msgIdtracker to prevent double message
413
+ //use #msgTimeTracker to limit inbound message 1msg/s
389
414
  if(message){
390
415
  const msgID = msgId+id
391
- if(!this.#msgIdtracker.includes(msgID)){
392
- this.#msgIdtracker.push(msgID)
416
+ let oldmsgtime = 0
417
+ let newmsgtime = new Date().getTime()
418
+ if(this.#msgTimeTracker.has(id))oldmsgtime = this.#msgTimeTracker.get(id)
419
+ const msgtimelimit = 1000
420
+ if(!this.#msgIdtracker.has(msgID) && newmsgtime-oldmsgtime>msgtimelimit){
421
+ this.#msgIdtracker.set(msgID,newmsgtime)
422
+ this.#msgTimeTracker.set(id,newmsgtime)
393
423
  this.#rooms[room].onMessage(message,id)
394
424
  }
395
425
  }
@@ -695,6 +725,7 @@ class webpeerjs{
695
725
  this.#peerDiscoveryHybrid()
696
726
  this.#trackHybridPeersConnection()
697
727
  this.#trackWebpeerConnection()
728
+ this.#garbageCollectionMsgIdTracker()
698
729
  },10e3)
699
730
 
700
731
 
@@ -774,6 +805,11 @@ class webpeerjs{
774
805
  onMessage : () => {},
775
806
  listenMessage : f => (this.#rooms[room] = {...this.#rooms[room], onMessage: f}),
776
807
  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
777
813
  const msgId = (new Date()).getTime()
778
814
  const data = JSON.stringify({prefix:config.CONFIG_PREFIX,room,message,id:this.#libp2p.peerId.toString(),msgId})
779
815
  const arr = uint8ArrayFromString(data)
@@ -809,12 +845,25 @@ class webpeerjs{
809
845
  mddrs.push(mddr)
810
846
  this.#dialMultiaddress(mddrs)
811
847
  }
848
+
849
+ plugin(callback){
850
+ callback(this)
851
+ }
812
852
 
813
853
 
814
854
  /*
815
855
  PRIVATE FUNCTION
816
856
  */
817
857
 
858
+ #garbageCollectionMsgIdTracker(){
859
+ const limit = 60*1000
860
+ for(const msg of this.#msgIdtracker){
861
+ if(msg[1] > limit){
862
+ this.#msgIdtracker.delete(msg[0])
863
+ }
864
+ }
865
+ }
866
+
818
867
  //track hybrid peer connection and try to dial if not connected at least 1
819
868
  #trackHybridPeersConnection(){
820
869
  let isConnectedToHybridPeers = false
@@ -1082,6 +1131,7 @@ class webpeerjs{
1082
1131
 
1083
1132
  if(!navigator.onLine)return
1084
1133
  if(!this.#isDialEnabled)return
1134
+ if(this.#connectedPeers.size > 5)return
1085
1135
 
1086
1136
  for(const target of config.CONFIG_KNOWN_BOOTSTRAP_HYBRID_IDS){
1087
1137
  if(!this.#isConnected(target) && !this.#connections.has(target)){
@@ -1116,7 +1166,7 @@ class webpeerjs{
1116
1166
 
1117
1167
  //check the last seen in web peer
1118
1168
  #trackLastSeen(){
1119
- const timeout = 10*1000
1169
+ const timeout = 20*1000
1120
1170
  const forcetimeout = 60*1000
1121
1171
  const now = new Date().getTime()
1122
1172
 
@@ -1126,7 +1176,7 @@ class webpeerjs{
1126
1176
  const last = peer[1].last
1127
1177
  const time = now-last
1128
1178
  if((time>timeout && !this.#isConnected(id))||(time>forcetimeout)){
1129
-
1179
+ //console.log('time',time)
1130
1180
  this.#connectedPeers.delete(id)
1131
1181
  this.#updatePeers()
1132
1182
  this.#onDisconnectFn(id)
@@ -1187,20 +1237,11 @@ class webpeerjs{
1187
1237
  }
1188
1238
  else{
1189
1239
  if((nodePeerCount>(limitCount-5))||(allPeerCount>(config.CONFIG_MAX_CONNECTIONS-5))){
1190
- //close random peers
1191
- let peers = []
1192
- for(const peer of this.#libp2p.getPeers()){
1193
- peers.push(peer.toString())
1194
- }
1195
- const randomKey = Math.floor(Math.random() * peers.length)
1196
- const randompeerid = peers[randomKey]
1197
- if(!config.CONFIG_KNOWN_BOOTSTRAP_HYBRID_IDS.includes(id)){
1198
- await this.#libp2p.hangUp(peerIdFromString(randompeerid))
1199
- }
1240
+ return
1200
1241
  }
1201
1242
  }
1202
1243
 
1203
- if(this.#webPeersId.includes(id) || config.CONFIG_KNOWN_BOOTSTRAP_PEERS_IDS.includes(id) || config.CONFIG_KNOWN_BOOTSTRAP_HYBRID_IDS.includes(id)){
1244
+ if(this.#webPeersId.includes(id) || config.CONFIG_KNOWN_BOOTSTRAP_HYBRID_IDS.includes(id)){
1204
1245
  this.#dialQueue.unshift(mddrs)
1205
1246
  }
1206
1247
  else{
@@ -1382,19 +1423,9 @@ class webpeerjs{
1382
1423
  }
1383
1424
  }
1384
1425
  },45*1000)
1385
- }
1386
-
1387
-
1388
- //track for good connection
1389
- async #connectionTracker(){
1390
-
1391
- for await (const { key, value } of this.#dbstore.query({})) {
1392
- const id = key.toString().split('/')[1]
1393
- const addr = new TextDecoder().decode(value)
1394
- this.#dbstoreData.set(id,addr)
1395
- }
1426
+ }
1396
1427
 
1397
- setInterval(async ()=>{
1428
+ async #checkConnectionAll(){
1398
1429
 
1399
1430
  //save peer address if connection is good
1400
1431
  const connections = this.#libp2p.getConnections()
@@ -1422,12 +1453,26 @@ class webpeerjs{
1422
1453
 
1423
1454
  }
1424
1455
 
1456
+ const shuffle = (array) => {
1457
+ for (let i = array.length - 1; i > 0; i--) {
1458
+ const j = Math.floor(Math.random() * (i + 1));
1459
+ [array[i], array[j]] = [array[j], array[i]];
1460
+ }
1461
+ return array;
1462
+ };
1425
1463
 
1426
1464
  //connect to saved best peer address
1427
1465
  //working great
1428
- for(const peer of this.#dbstoreData){
1429
- const id = peer[0]
1430
- const addr = peer[1]
1466
+ const bestall = Array.from(this.#dbstoreData.keys())
1467
+ const bestshuffle = shuffle(bestall)
1468
+ const best = bestshuffle.slice(0, 10)
1469
+ for(const hybrid of config.CONFIG_KNOWN_BOOTSTRAP_HYBRID_IDS){
1470
+ if(best.includes(hybrid))continue
1471
+ if(!bestall.includes(hybrid))continue
1472
+ best.unshift(hybrid)
1473
+ }
1474
+ for(const id of best){
1475
+ const addr = this.#dbstoreData.get(id)
1431
1476
  if(this.#isConnected(id)){
1432
1477
  this.#connectionTrackerStore.set(id,0)
1433
1478
  continue
@@ -1455,6 +1500,7 @@ class webpeerjs{
1455
1500
  let mddrs = []
1456
1501
  const mddr = multiaddr(addr)
1457
1502
  mddrs.push(mddr)
1503
+ //console.log(id,addr)
1458
1504
  this.#dialMultiaddress(mddrs)
1459
1505
  }
1460
1506
  }
@@ -1480,7 +1526,20 @@ class webpeerjs{
1480
1526
  }
1481
1527
  }
1482
1528
  }
1483
-
1529
+ }
1530
+ //track for good connection
1531
+ async #connectionTracker(){
1532
+
1533
+ for await (const { key, value } of this.#dbstore.query({})) {
1534
+ const id = key.toString().split('/')[1]
1535
+ const addr = new TextDecoder().decode(value)
1536
+ this.#dbstoreData.set(id,addr)
1537
+ }
1538
+
1539
+ this.#checkConnectionAll()
1540
+
1541
+ setInterval(async ()=>{
1542
+ this.#checkConnectionAll()
1484
1543
  },15*1000)
1485
1544
  }
1486
1545
 
@@ -1863,6 +1922,9 @@ class webpeerjs{
1863
1922
  listenaddress.push('/webrtc')
1864
1923
  }
1865
1924
 
1925
+ const stunurls = config.CONFIG_WEBRTC_STUN_URLS
1926
+ const stunurlsbackup = config.CONFIG_WEBRTC_STUN_URLS_BACKUP
1927
+
1866
1928
  const turnurls = atob(config.CONFIG_WEBRTC_TURN_HOST)
1867
1929
  const turnusername = atob(config.CONFIG_WEBRTC_TURN_USER)
1868
1930
  const turncredential = atob(config.CONFIG_WEBRTC_TURN_PWD)
@@ -1871,94 +1933,120 @@ class webpeerjs{
1871
1933
  const turnusernamebackup = atob(config.CONFIG_WEBRTC_TURN_USER_BACKUP)
1872
1934
  const turncredentialbackup = atob(config.CONFIG_WEBRTC_TURN_PWD_BACKUP)
1873
1935
 
1874
- const ice = await new Promise((resolve)=>{
1875
-
1876
- let stun = false
1877
- let turn = false
1878
-
1879
- const timeout = setTimeout(()=>{
1880
- let ice = []
1881
- if(stun){
1882
- ice.push(stun)
1883
- }else{
1884
- const backup = {
1885
- urls: config.CONFIG_WEBRTC_STUN_URLS_BACKUP
1886
- }
1887
- ice.push(backup)
1888
- }
1889
- if(turn){
1890
- ice.push(turn)
1891
- }else{
1892
- const backup = {
1893
- urls: turnurlsbackup,
1894
- username: turnusernamebackup,
1895
- credential: turncredentialbackup
1896
- }
1897
- ice.push(backup)
1898
- }
1899
- resolve(ice)
1900
- },5000)
1901
-
1902
- function check(){
1903
- if(stun && turn){
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(()=>{
1904
1943
  let ice = []
1905
1944
  ice.push(stun)
1906
1945
  ice.push(turn)
1907
- clearTimeout(timeout)
1908
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
+ }
1909
1957
  }
1910
- }
1911
-
1912
- //test ice servers
1913
-
1914
- const iceServers = [
1915
- {
1916
- urls: config.CONFIG_WEBRTC_STUN_URLS
1917
- },
1918
- {
1919
- urls: turnurls,
1920
- username: turnusername,
1921
- credential: turncredential
1922
- }
1923
- ];
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
+ ];
1924
1971
 
1925
- const pc = new RTCPeerConnection({
1926
- iceServers
1927
- });
1972
+ const pc = new RTCPeerConnection({
1973
+ iceServers
1974
+ });
1928
1975
 
1929
- pc.onicecandidate = (e) => {
1930
- if (!e.candidate) return;
1976
+ pc.onicecandidate = (e) => {
1977
+ if (!e.candidate) return;
1931
1978
 
1932
- //console.log(e.candidate.candidate);
1979
+ //console.log(e.candidate.candidate);
1933
1980
 
1934
- // stun works
1935
- if(e.candidate.type == "srflx"){
1936
- //console.log('publicip',e.candidate.address);
1937
- stun = {
1938
- urls: config.CONFIG_WEBRTC_STUN_URLS
1939
- }
1940
- check()
1941
- }
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
+ }
1942
1989
 
1943
- // turn works
1944
- if(e.candidate.type == "relay"){
1945
- turn = {
1946
- urls: turnurls,
1947
- username: turnusername,
1948
- credential: turncredential
1949
- }
1950
- check()
1951
- }
1952
- };
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
+ };
1953
2000
 
1954
- pc.onicecandidateerror = (e) => {
1955
- console.debug(e);
1956
- };
2001
+ pc.onicecandidateerror = (e) => {
2002
+ console.debug(e);
2003
+ };
1957
2004
 
1958
- pc.createDataChannel('webpeerjs');
1959
- pc.createOffer().then(offer => pc.setLocalDescription(offer));
1960
- })
1961
- //console.log(ice)
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]
2016
+ }
2017
+
2018
+ //set rtc configuration
2019
+ if(configuration.rtcConfiguration === undefined){
2020
+
2021
+ ice = await checkice(stunurls,turnurls,turnusername,turncredential,5000)
2022
+
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)
2044
+
2045
+ configuration.rtcConfiguration = {
2046
+ iceServers: ice,
2047
+ }
2048
+ }
2049
+
1962
2050
 
1963
2051
  //create libp2p instance
1964
2052
  const libp2p = await createLibp2p({
@@ -1969,9 +2057,7 @@ class webpeerjs{
1969
2057
  webTransport(),
1970
2058
  webSockets(),
1971
2059
  webRTC({
1972
- rtcConfiguration: {
1973
- iceServers: ice,
1974
- },
2060
+ rtcConfiguration: configuration.rtcConfiguration,
1975
2061
  }),
1976
2062
  circuitRelayTransport({
1977
2063
  discoverRelays: config.CONFIG_DISCOVER_RELAYS,