ipfs / js-ipfs

IPFS implementation in JavaScript
https://js.ipfs.tech
Other
7.44k stars 1.25k forks source link

Not seeing any connected peers when using js-ipfs in browser #800

Closed zabirauf closed 7 years ago

zabirauf commented 7 years ago

I have the following code to connect to IPFS

const repoPath = String(Math.random());
const node = new IPFS({
  repo: repoPath,
  IpfsDataDir: '/tmp/testipfs-zabirauf-7',
  // dev server: webrtc-star-signalling.cloud.ipfs.team
  SignalServer: 'star-signal.cloud.ipfs.team', // IPFS dev server
  Discovery: {
    MDNS: {
      Enabled: false,
      Interval: 10
    },
    webRTCStar: {
      Enabled: true
    }
  },
});

// Create the IPFS node instance
    node.init({ emptyRepo: true, bits: 2048 }, (err: any) => {
        if (err) {
            throw err;
        }

        node.load((err: any) => {
            if (err) {
                throw err;
            }
            node.goOnline((err: any) => {
                if (err) {
                    throw err;
                }
                node.id().then((res: any) => {
                    // TEST
                    (<any>window).ipfsNode = node;
                    callback(<IdResponse>res);
                });
            });
        });
    });

The node is connected, isOnline is true but when I get the list of peers I get nothing. Even when trying to get a file, nothing. Is there a known issue in using js-ipfs in browser or is there something wrong in the code I have to connect to IPFS?

victorb commented 7 years ago

First it should be a lot simpler to use js-ipfs now. You could something like this instead:

// Create the IPFS node instance
const node = new IPFS()

node.on('start', () => {
  // Your now is ready to use \o/

  // stopping a node
  node.stop(() => {
    // node is now 'offline'
  })
})

Secondly, there might just not be any peers connected at the same time as you. Have you tried having two tabs open or two different browsers loading the same page and see if it still happens?

daviddias commented 7 years ago

@zabirauf where did you get such example of creating a IPFS instance? That options object doesn't really match the API.

As @VictorBjelkholm suggested, if you checkout js-ipfs master, you will have a new experience for init that is way simpler than before, what you are looking to is:

const node = new IPFS({
  repo: <repopath>,
  config: { // overload the default config
    Addresses: {
      Swarm: [
        '/libp2p-webrtc-star/dns4/star-signal.cloud.ipfs.team/wss'
      ]
    }
  }
})

node.on('start', () => {
  // Your now is ready to use \o/
})

Let me know if this works for you.

rodkeys commented 7 years ago

I am on js-ipfs master and I cannot find any peers as well. I am running Ubuntu 14.05.5 and node v6.7.0.

const node = new IPFS({
    repo: path.join(os.tmpdir() + '/' + new Date().toString()),
    config: { 
        Addresses: {
            Swarm: [
                '/libp2p-webrtc-star/dns4/star-signal.cloud.ipfs.team/wss'
            ]
        }
    }
})

node.on('start', () => {
        node.swarm.peers({}, function(err, peers) {
            console.log(peers)
        })
})
daviddias commented 7 years ago

Let's try one more thing, spawn several browser tabs with your code and instead of doing just once node.swarm.peers do it in a setInterval.

ZokosDev commented 7 years ago

@diasdavid that worked my peers are now showing up, thank you.

zabirauf commented 7 years ago

@diasdavid pulling from master and then starting it as you suggested made it work.

I got the config that I was using from this example from https://github.com/haadcode/orbit-db/blob/master/examples/browser/index.js

BTW is there a documentation on what are the different values of config and what each of them means?

daviddias commented 7 years ago

@zabirauf awesome to hear! Unfortunately, we have not, this is the closest -- https://github.com/ipfs/specs/tree/master/repo#config-state --, they should be, however, very intuitive. Wanna update the spec with the descriptions of those that you know, asking those you don't know?

Closing this issue for now as it was resolved :)

jgostylo commented 7 years ago

I was having a lot of issues with this as well and I am still not able to isolate my problem. I am using the hosted package for the browser at:

<script src="https://unpkg.com/ipfs/dist/index.js"></script>

I assume it is up to date.

I was going off the examples which seem to be a little out of date. I the behavior I was seeing was that my callback with node.files.cat(hash, callback) was never getting called. I feel like I traced through the code enough to see that WatchManager gets a blockListener set to listen for an event and because I never get the block I am requesting, the callback never gets triggered. I also eventually found out that with my setup I was not connecting to any peers so I thought I had found my issue and this thread would help resolve it for me.

Now I am using your suggested init and start, @diasdavid, and it looks like I am getting a peer because when I run node.swarm.peers(callback) I am getting a single peer in the list /libp2p-webrtc-star/dns4/star-signal.cloud.ipfs.team/wss/ipfs/QmSTqFzfSJSqsZCFnGiPUvdb3A1EpNxDBGfX9WgPno1T9H. Unfortunately I am getting the same behavior where my cat callback is never being executed and I believe it is because it is still not finding the block with my requested data.

This is the code I am using for the cat (and I have verified that resHash is a hash string that gets something when I am running go-ipfs):

        node.files.cat(resHash, function(err, stream){
          var data = '';

          stream.on('data', function(chunk){
            data += chunk.toString();
          });
          stream.on('error', function(err){
            console.error('Error getting file from IPFS:', err);
          });
          stream.on('end', function(){
            console.log(data);
          })
        });

I am a little at a loss as to where to go from here. Do I need to add more peers to the swarm array in the config? I thought that this was supposed to broadcast my presence and auto connect me to more peers. Am I messing things up (dropping peer connections) by being in debug and setting breakpoints?

daviddias commented 7 years ago

@jgostylo Thank you for the throughout issue report, I believe I understand what you are experiencing.

tl;dr You can't get a file that isn't within your reach and since we haven't implemented timeouts (see more why here: https://github.com/ipfs/interface-ipfs-core/issues/58), the call stays there waiting for the file to exist. That being said, if you issue a files.add of that file in another node, the callback should resolve.

v0.23 is not dialing automatically to Bootstraper nodes. We wanted to ship this feature but it was blocked to limited WebSockets support in the Bootstraper nodes at the time. The only peers you will find are the ones that are discovered through WebRTC, which means, only js-ipfs peers. To connect to go-ipfs nodes, you need to connect to peers directly with ipfs.swarm.connect. See more here: https://github.com/ipfs/js-ipfs/pull/740

Another note is that we are actively developing DHT and Relay, the two fundamental pieces that will enable js-ipfs browser nodes to connect to any node in the network without any manual configuration. You will get that 'seemless' experience you are looking for in v0.24 or v0.25, depending on how soon we finish that work. Track here: https://github.com/libp2p/js-libp2p-dht/pull/1 for DHT and https://github.com/libp2p/js-libp2p-circuit/pull/9 for Relay.

jgostylo commented 7 years ago

@diasdavid Thank you for the reply, explanation, and for working on this project. This kind of brings me back to where I was when I attempted to run manual connections before I knew about the alternate setup with webRTC. I list out my peers in go-ipfs and I select about a dozen of them to set up connections manually. Here is an example of code that I am using and the error I get (which I don't understand right now).

node.swarm.connect("/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", function(err){console.log("Connection error: ", err)})

And this is the error I am getting:

Connection error:  Error: No available transport to dial to
    at attemptDial (dial.js:84)
    at Swarm.dial (dial.js:28)
    at Node.dialByPeerInfo (index.js:226)
    at Node.dialByMultiaddr (index.js:215)
    at Function.connect.promisify (swarm.js:76)
    at Object.connect (index.js:34)
    at <anonymous>:1:16

I am tracing through the debugger and I get the the part in dial.js where it calls const tKeys = swarm.availableTransports(pi) and in there I see that it gets to the line return addr.decapsulate('ipfs') and when I run that with a toString() I get /ip4/104.131.131.82/tcp/4001 so it looks like information is being parsed out like it is supposed to but tKeys is getting length 0 as filter to dialable is empty so the error is thrown. My understanding really gets taxed with dialable. I am not sure what connect is looking for to have something it considers dialable.

daviddias commented 7 years ago

@jgostylo the address that you are trying to dial from the browser is a TCP one, a transport that unfortunately is not available in the Browser runtime, therefore a Browser node can't dial to a node listing on TCP.

In the browser there is only support for WebSockets and WebRTC (we could add HTTP, but wouldn't bring any value at the moment). You need to make your Node listen on WebSockets.

The transfer-files tutorial explains how to do that https://github.com/ipfs/js-ipfs/tree/master/examples/transfer-files#2-make-your-daemons-listen-on-websockets

jgostylo commented 7 years ago

@diasdavid, Ok so it looks as if connection to the outside world will require a running daemon locally on the machine and then connecting the browser run js-ipfs to the websocket enable daemon. What I am eventually trying to do is have a browser client that can contact the broader ipfs world and grab data that it did not add itself. Does this following idea make sense then?: If there was a client that was set up that connected through websocket to a daemon then connecting through webRTC to a greater network would also give those browsers connected access to the greater IPFS network through the daemon? Does the current webRTC network connect clients over the internet?

mishfit commented 6 years ago

@diasdavid https://github.com/ipfs/js-ipfs/tree/master/examples/transfer-files#2-make-your-daemons-listen-on-websockets appears to be stale, is there a newer set of examples about websocket transport?

victorb commented 6 years ago

@mishfit new link: https://github.com/ipfs/js-ipfs/tree/master/examples/exchange-files-in-browser#2-make-your-daemons-listen-on-websockets

harrshasri commented 6 years ago

@diasdavid Is there any way to connect using socket.io. In case the websockets are unavailable instead of connecting locally to the daemon?