given my go-ipfs generated config:
"Addresses": {
"Swarm": [
"/ip4/0.0.0.0/tcp/4001",
"/ip6/::/tcp/4001"
],
"API": "/ip4/127.0.0.1/tcp/5001",
"Gateway": "/ip4/127.0.0.1/tcp/8080"
},
running the js-ipfs daemon will die with
Initializing daemon...
Starting at /home/noffle/.ipfs
Finished loading
error listen EADDRINUSE :::4001
Works fine if I remove the /ip6 address.
What if you remove the /ip4? :::4001 doesn't look right
It is true because we start a listener per multiaddr. Node.js TCP implementation starts a listener automatically on an IPV6 addr and IPV4, so the second time you listen, you are trying to listen on the same port.
Possible solution: Do addr matching and avoid trying to listen on equivalent addresses.
Workaround: We've been removing the ipv6 addr since we don't need it. It would be good to not have to worry about it though.
can we stop/disable node from auto listening on ip6? I think that would be the best solution
@dignifiedquire not that I know or managed to find somewhere how to do it.
There are unix socket options for that, I don't recall the exact name (SOL_SOMETHING) or how to set socket options in nodejs.
@noffle is this issue still happening for you? I have the same config but the js-ipfs daemon isn't choking
@shamb0t yup, still happening
It's the IPv6 socket binding to IPv4:
IPV6_V6ONLY (since Linux 2.4.21 and 2.6)
If this flag is set to true (non-zero), then the socket is restricted to sending and receiving IPv6 packets only. In this case, an IPv4 and an IPv6 application can bind to a single port at the same time.
If this flag is set to false (zero), then the socket can be used to send and receive packets to and from an IPv6 address or an IPv4-mapped IPv6 address.
Using it in Node seems to require the use of ffi or a compiled extension.
@shamb0t here is more input: You are not seeing the error now cause I removed the IPV6 port from the default config to avoid new users getting hit by that -> https://github.com/ipfs/js-ipfs/commit/e98368ea8b17363758215ad7eb775f467936edff#diff-ce4bf744aff5c27c180e317f04bedab0L5
What @noffle is seeing, is that if you do an ipfs init with go-ipfs and then use that repo with js-ipfs, it will choke.
We still need a fix for this on the js-libp2p-tcp transport where we filter the 'equivalent' IP addrs. Note that IPV6 has a bunch of possible combinations that result to the one of listening in any interface (0.0.0.0)
@diasdavid config file is generated from (go)ipfs init and the jsipfs daemon isn't choking. I added the line you removed from the default-config and still no choking. Should it choke if I regenerate the config with jsipfs init? Seems to be working fine for me...Im on osx 10.10
@shamb0t @noffle would you like to handle this one?
@shamb0t as we talked offline, this is only visible in Linux. Can you verify with a test and CI? (CI is Linux)
@diasdavid what's the actual plan of action here?
@dignifiedquire Making sure that having both IPv6 and IPv4 addresses for the same port doesn't crash on Linux. To achieve this, what I've been think through is that, since this is a net module implementation detail, the libp2p-tcp transport instance should keep a tab of the listeners that it started, so that if it started a listener in IPv4 and then tries to start a listener in IPv6 on the same mapped addr, it will just return the same listener.
I thought I would tackle this issue but I am unable to reproduce the problem. I'm running on a MAC with the following config:
"Addresses": {
"Swarm": [
"/ip4/0.0.0.0/tcp/4001",
"/ip6/::/tcp/4001"
],
"API": "/ip4/127.0.0.1/tcp/5001",
"Gateway": "/ip4/127.0.0.1/tcp/8080"
},
I start the daemon with the following code:
var IPFS = require ('../../git/js-ipfs/src/index.js');
var node = new IPFS();
node.goOnline(function(){});
I receive the following message:
Sids-MacBook-Pro:js-ipfs sidharder$ node index.js
Promise { { version: '0.17.0', repo: '', commit: '' } }
Swarm listening on /ip4/127.0.0.1/tcp/4001
Swarm listening on /ip4/10.1.4.129/tcp/4001
Swarm listening on /ip6/::/tcp/4001
@SidHarder seems the problem only affects Linux. Maybe you could try it in a VM or in a Docker container based on some Linux dist?
@diasdavid I was able to reproduce this problem on an Ubuntu server. One solution that I implemented that seems to work was to add a distinctMultiaddr method to the peerInfo object which creates a new array of multiaddrs that doesn't contain any duplicate IP/Ports. I then called this method in the transport object when it's time to build the multiaddrs array just before the createListeners method is called. The distinctMultiaddr function will choose the first distinct addresses/ports and drop others as it loops through the addresses. The filter code is a bit messy. Does this sound like a reasonable approach or did you have something else in mind.
@SidHarder it sounds that what you build is what we need, just a couple of questions:
@diasdavid The distinctMultiaddrs method doesn't favor either ipv4 or ipv6, it simply keeps the first equivalent IP and port and ignores any subsequent with same IP/Port. So the addresses that will be listened on can be modified by changing the order of addresses in the config file. I'm afraid I don't know how Node favors IPV4 vs IPV6.
I'm not sure how to answer the question "Are you filtering for all the transports". I'm simply taking the multiaddrs array and making sure there are no duplicate ip/ports. Am I missing something here?
Question?? So basically what I did was clone the master js-ipfs repo and then ran npm install which installed all the additional modules. I then went into the node_modules folder and made the following changes:
To submit theses changes I will clone the two repositories that these files are in, make the changes and then create two separate pr's. What I don't feel comfortable with is that in this scenario I haven't exactly test the code that I'm submitting. Do you see a problem with this? How would you approach this?
I haven't read full thread here but here is how IPv6 sockets work on linux:
When you call open on a IPv6 socket fd with address: localhost, anybind or special addresses that is mapping IPv4 space to IPv6 it will open both IPv4 and v6 endpoints in kernel.
There is special flag (IPV6_V6ONLY ) for socket syscall that blocks binding IPv4 address when socket with corresponding IPv6 address is bound. For more see: https://linux.die.net/man/7/ipv6
I just finished testing js-ipfs on ubuntu with ipv4 and ipv6 on port 5001, daemon is not choking any more.
I can verify that it's working for me as well now, I'm on Ubuntu 16.04.1 LTS
Wohooo! :D thank you @SidHarder !