libp2p / js-libp2p

The JavaScript Implementation of libp2p networking stack.
https://libp2p.github.io/js-libp2p/
Other
2.33k stars 445 forks source link

Failed Peer Discovery #777

Closed kottackalsulvin closed 4 years ago

kottackalsulvin commented 4 years ago

Hi,

I am working on a webcam app using libp2p. Inorder to connect the peers, I tried the below libp2p code but it didn’t worked for me.

App.js Code

const SIGNAL_SERVER = '/ip4/127.0.0.1/ws/p2p-webrtc-star/ipfs/:peer-id'

const node = new Node({peerInfo})

// start libp2p

node.start((err) => {
console.log("in start node");
if (err) callback(err)
callback(null, node)
})

...........
............

class Node extends libp2p {

//The options to use when generating the libp2p node

constructor (peerInfo, peerBook, options) {  
options = options || {}
const wstar = new WebRTCStar({ wrtc })

// The libp2p module

const defaults = {
modules: {
transport: [ new WS(), wstar ],
streamMuxer: [ mplex ],
connEncryption: [ secio ],
peerDiscovery: [wstar.discovery ],
}
}
super(defaultsDeep(defaults,
}
}
.............
.................
node.on('peer:discovery', (peerInfo) => {
console.log('Peer Discovered:')
})

It didn’t displays any error but the peers are not discovering each other.Please help me to resolve this issue.

Environment

Npm:6.13.4 Node:10.18.1 Libp2p:0.25.4 libp2p-webrtc-star: 0.13.2 libp2p-websockets: 0.12.2

jacobheun commented 4 years ago

Have you tried upgrading to libp2p 0.29? There have been some significant updates since 0.25

kottackalsulvin commented 4 years ago

@jacobheun Thanks for your reply. I upgraded to libp2p 0.26.2, but nothing changed. The below error is shown, when upgraded to 0.29.0

ERROR in ./node_modules/abortable-iterator/index.js
Module parse failed: Unexpected token (13:17)
You may need an appropriate loader to handle this file type.
|   signals = signals.map(({ signal, options }) => ({ signal, options: options || {} }))
| 
|   async function * abortable () {
|     let nextAbortHandler
|     const abortHandler = () => {
 @ ./node_modules/libp2p-utils/src/stream-to-ma-conn.js 3:18-47
 @ ./node_modules/libp2p/src/circuit/index.js
 @ ./node_modules/libp2p/src/index.js
 @ ./app/backend/app.js
 @ multi (webpack)-dev-server/client?http://localhost:8081 ./app/backend/app.js
kottackalsulvin commented 4 years ago

webpack.config.js

module: {
    rules: [
      {
      test: /\.js$/,
             exclude: {
          test: /(node_modules|bower_components)/,
         not: [/libp2p/,/p-queue/,/orbit-db-access-controllers/]
        },
      use: {
        loader: 'babel-loader',
        options: {
          presets: [
            [
              'env',
              {
                targets: {
                  node: '10.18.0'
                }
              }
            ]
          ],
          plugins: [
            'transform-object-rest-spread',
            'transform-class-properties'
          ]
        }
      }
    }
  ]
  },

  node:{
    dgram:'empty',
    fs:'empty',
    net:'empty',
    tls:'empty'
  }
jacobheun commented 4 years ago

The error from 0.29 is because you need to use a modern JS preset for babel like https://babeljs.io/docs/en/babel-preset-env, to handle the async generators. See the js-ipfs webpack example for reference https://github.com/ipfs/js-ipfs/blob/ipfs%400.50.2/examples/browser-webpack/webpack.config.js#L36

kottackalsulvin commented 4 years ago

@jacobheun Thank you, that resolved my issue in webpack. But while running the app, below error is shown

Uncaught TypeError: Cannot read property 'toB58String' of undefined

App.js

const PeerId = require('peer-id');
const PeerInfo = require('peer-info');

startOwnPeerfn: function () { 
const startOwnPeer = (callback) => {
PeerId.create((err, peerId) => { 
if (err) callback(err)

const SIGNAL_SERVER = '/ip4/127.0.0.1/ws/p2p-webrtc-star/ipfs/:peer-id' 

const peerInfo = new PeerInfo(peerId)
const peerBook = new PeerBook()
const mh1 = Multiaddr(SIGNAL_SERVER.replace(':peer-id', peerId.toB58String()))
const peerIdd = mh1.getPeerId()
peerInfo.multiaddrs.add(mh1);

const node = new Node({peerInfo})

node.start((err) => {
console.log("in start node");
if (err) callback(err)
callback(null, node)
})
})
}

startOwnPeer((err, node) => {
console.log("in window start own peer");
})
}
vasco-santos commented 4 years ago

@kottackalsulvin From an initial analysis this seems related to using peer-info, which was deprecated in libp2p@0.28. You can see how to change this in libp2p/js-libp2p/doc/migrations/v0.27-v0.28.md#migrating-from-peer-info.

It also seems you are still using callbacks and peerBook, which are also not used anymore. I highly recommend you check the migration guides available while updating to 0.29

kottackalsulvin commented 4 years ago

@vasco-santos How to connect peers in the browser? Peers are discovered but cannot dial to other peers.

App.js

startOwnPeerfnVideo: function () {

//const wstar = new WebRTCStar({ wrtc })

;(async () => { const node = await libp2p.create({ addresses: { listen: [ '/dns4/wrtc-star1.par.dwebops.pub/tcp/443/wss/p2p-webrtc-star', '/dns4/wrtc-star2.sjc.dwebops.pub/tcp/443/wss/p2p-webrtc-star' ] }, modules: { transport: [WS, WebRTCStar], connEncryption: [secio], streamMuxer: [mplex], // peerDiscovery:[wstar.discovery]​ }

})

node.on('peer:discovery', (peerId) => { console.log('Discovered:', peerId.toB58String()) //peers discovered })

node.connectionManager.on('peer:connect', (connection) => { console.log('Connection established to:', connection.remotePeer.toB58String()) }) await node.start() })(); },

vasco-santos commented 4 years ago

This seems good. Perhaps version issues.

Please check this example. You can remove the bootstrap module in it. The remaining code seems the same as yours. Double check the example versions and yours

kottackalsulvin commented 4 years ago

Do we need any peer mechanisms like mdns or kadDHT for connecting peers?

vasco-santos commented 4 years ago

Do we need any peer mechanisms like mdns or kadDHT for connecting peers?

webrtc-star offers a peer discovery module, that is automatically used if provided as a transport. Also, the autoDial option is true by default, which makes libp2p automatically dial discovered peers.

mdns does not work in the browser and libp2p-kad-dht needs to be improved. So, you should be good with webrtc-star and bootstrap. But, it might depend on your use case.

kottackalsulvin commented 4 years ago

@vasco-santos Thank you so much for your help. I tried to replicate the webcam example [https://github.com/prcolaco/webcam-stream-libp2p] and have used ‘it-pipe’ to stream data to other connected peers. But am getting the below error. I can’t figure out where am wrong.

Error: no protocol with name: QmWFRVjz8GRUXesYbwbEUCWpftg31QyHAD7Jv9bfjqnFvP

App.js

node.on('peer:discovery', (peerId) => {
console.log('Discovered:', peerId.toB58String())
const id = peerId.toB58String()
node.connectionManager.on('peer:connect', (connection) => {
console.log("Connected to "+connection.remotePeer.toB58String())
const listenerMultiaddr = '/dns4/wrtc-star1.par.dwebops.pub/tcp/443/wss/p2p-webrtc-star/' + connection.remotePeer.toB58String()
;(async () => {
const { stream } = await node.dialProtocol(listenerMultiaddr, '/ipfs/bitswap/1.1.0')
await pipe(
['my own protocol, wow!'],
stream,
async function (source) {
for await (const data of source) {
console.log("inn stream");
console.log(data.toString())
// Create a canvas for this peer
// App.createCanvas(id);
}
}
)
})();
})
})
vasco-santos commented 4 years ago

Hey @kottackalsulvin

Your issue is on the listenerAddr: It is throwing on https://github.com/multiformats/js-multiaddr/blob/master/src/protocols-table.js#L15 . So, you are mising the /p2p/ part before the peerId. An example would be: /dns4/wrtc-star2.sjc.dwebops.pub/tcp/443/wss/p2p-webrtc-star/p2p/QmcvtvDS2fPcXmgcq87D4Ny1yxzmonFNEffEhsBazouKqr

kottackalsulvin commented 4 years ago

Error

Uncaught (in promise) AggregateError: 
    Error: protocol selection failed

Didn't resolved.

vasco-santos commented 4 years ago

Can you push the code somewhere I can test it with instructions? If not, I need more information to replicate this: Module versions, logs (in the browser do localStorage.debug = 'libp2p.*') and flow that lead to this

kottackalsulvin commented 4 years ago

App.js

startOwnPeerfnVideo: function () { 
const createNode = async () => {
const node = await libp2p.create({
addresses: {
listen: [
'/dns4/wrtc-star2.sjc.dwebops.pub/tcp/443/wss/p2p-webrtc-star' 
] 
},
modules: {
transport: [WS, WebRTCStar],
connEncryption: [NOISE],
streamMuxer: [mplex]
},
}) 
const myID = node.peerId.toB58String();
console.log('Your ID: ' + myID)
//App.createCanvas(myID);
App.listenAndConnectToPeers(node);
await node.start()
return node
}
;(async () => {
const node = await createNode()
console.log('node has started (true/false):', node.isStarted())
console.log('listening on:')
node.multiaddrs.forEach((ma) => console.log(`${ma.toString()}/p2p/${node.peerId.toB58String()}`))
})();
},

listenAndConnectToPeers:function(node){
node.on('peer:discovery', (peerId) => {
const id = peerId.toB58String()
node.connectionManager.on('peer:connect', (connection) => {
console.log("Ccconnected to "+connection.remotePeer.toB58String())
;(async () => {
const { stream } = await node.dialProtocol(`${node.multiaddrs}/p2p/${id}`, '/ipfs/bitswap/1.1.0')
// await pipe(
// ['node 1 dialed to node 2 successfully'],
// stream
// )
})();
})
})
}
vasco-santos commented 4 years ago

Thanks, I think I got the issue.

You are trying to open a stream using IPFS's bitswap protocol which the other peer is not running. Do you want to use bitswap? If yes, I recommend using IPFS directly. If not and you were just experimenting, I recommend you create your own protocol for testing.

To create a new protocol, you will need your peers to have an handler for the protocol (imagine a REST API handler) and then open a stream from another one. You should check this example. It has a simple chat protocol where the listener has the handler. In your case, I believe all your peers will be listeners and dialers.

One more thing, considering that you are opening the stream within the node.connectionManager.on('peer:connect', (connection) => {}, I recommend leveraging the connection itself: https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/connection#create-a-new-stream

kottackalsulvin commented 4 years ago

@vasco-santos Thanku for your help.That resolved my issue when I changed the protocol. How to know if a particular peerId is connected or not in libp2p 0.29?

vasco-santos commented 4 years ago

@vasco-santos Thanku for your help.That resolved my issue when I changed the protocol.

Good to hear

How to know if a particular peerId is connected or not in libp2p 0.29?

https://github.com/libp2p/js-libp2p/blob/master/doc/API.md#connectionmanagerget

jacobheun commented 4 years ago

Pasting unformatted code makes it really difficult to figure out what's going on, please post formatted code in the future. As far as I can tell based on your logs you are sending and receiving data. I'm not very familiar with canvas, but my best guess is that the data going into the render on the receiving side is not correct.

Also, you should NOT make your custom protocol /ipfs/bitswap/3.0.0 as it's not Bitswap. You should namespace this to your application.

I'm going to close this issue as the original problem has been solved and there isn't an underlying issue with libp2p here. Support requests should be made on the forums, https://discuss.libp2p.io/, we're happy to help there.