Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(swarm): add dnsaddr support in swarm connect #5535

Merged
merged 6 commits into from
Mar 19, 2019

Conversation

overbool
Copy link
Contributor

Fixes: #5522

License: MIT
Signed-off-by: Overbool overbool.xu@gmail.com

if err != nil {
return nil, err
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
Copy link
Contributor

@michaelavila michaelavila Sep 28, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've looked through this whole PR and everything makes sense to me 👍. I do have a question about how these timeouts are specified in go-ipfs (both here and more generally). I notice lines like the following (and there are a handful):

https://github.com/ipfs/go-ipfs/blob/master/core/bootstrap.go#L60

And also lines like yours (e.g.):

https://github.com/ipfs/go-ipfs/blob/master/core/commands/pubsub.go#L178

Is there a rule of thumb for deciding when to specify these timeouts with a name vs inline?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, we should probably name this. We just get lazy sometimes.

Copy link
Member

@Stebalien Stebalien left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, this subtly changes some important semantics. Now, if I run ipfs swarm connect /dnsaddr/a.b.c/ipfs/QmPeer, we'll insert the resolved addrs into the peerstore instead of the dnsaddr. That means future connects won't try resolving the dnsaddr again. They'll instead use the resolved addresses, never learning about any changes to this DNS record.

I wonder if we should instead:

  1. For each address that doesn't end in /ipfs/Qm..., resolve it.
  2. After resolving it, parse it but ignore everything but the peer ID.
  3. Create a IPFSAddr structs out of the original (unresolved) dnsaddrs and these peer IDs.

Thoughts @hsanjuan @overbool?

if err != nil {
return nil, err
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, we should probably name this. We just get lazy sometimes.

return nil, err
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
raddrs, err := madns.Resolve(ctx, maddr)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we parallelize this?

if len(raddrs) == 0 {
return nil, fmt.Errorf("non-resolvable multiaddr about %v", maddr)
}
maddrs = append(maddrs, raddrs...)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we may need to filter out addresses that still don't end in /ipfs/Qm....

@hsanjuan
Copy link
Contributor

we'll insert the resolved addrs into the peerstore instead of the dnsaddr.

Maybe this has changed, but do unresolved addresses in the peerstore get resolved when building a connection? My impression when I was testing this a while ago is they didn't. I remember a discussion or PR in which @lanzafame was involved (??) suggesting to do this at a lower level in libp2p.

A few months back, addresses were only resolved in basichost.Connect (https://github.com/libp2p/go-libp2p/blob/master/p2p/host/basic/basic_host.go#L383) but normally things will use NewStream directly and I think (i might be wrong) that that codepath does not resolve if it has to open a new connection.

So might be better off storing resolved addresses for the moment?

@Stebalien
Copy link
Member

Ah... No, they don't. That's broken. Yeah, you're right. But we should really fix this. We don't even do routing on that path.

@overbool
Copy link
Contributor Author

overbool commented Sep 29, 2018

For each address that doesn't end in /ipfs/Qm..., resolve it.

@Stebalien Did you mean that if address ends in /ipfs/Qm..., we don't need to resolve it, because it will resolve address inner the basichost.Connect?

However, I don't think it will solve the issue as mentioned:

They'll instead use the resolved addresses, never learning about any changes to this DNS record.

@overbool
Copy link
Contributor Author

overbool commented Oct 5, 2018

@Stebalien I had made some changes according to your suggestion.

Copy link
Member

@Stebalien Stebalien left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delay, I've been trying to push through a change that will make it easier to do this correctly (although, in retrospect, it was always possible).

return nil, err
}
// check whether address ends in `ipfs/Qm...`
if _, err := maddr.ValueForProtocol(ma.P_IPFS); err != ma.ErrProtocolNotFound {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delay, I've been trying to push through a change to make this check more robust. You can now use:

if _, last := ma.SplitLast(maddr); last.Protocol().Code == ma.P_IPFS {
    maddrs = append(maddrs, maddr)
    continue
}

The current check will trip over relay addrs. That is, /p2p/QmRelayId/p2p-circuit/dnsaddr/foo.com will pass the check but doesn't end in /p2p/QmTargetId.

// filter out addresses that still doesn't end in `ipfs/Qm...`
for _, raddr := range raddrs {
if _, err := raddr.ValueForProtocol(ma.P_IPFS); err != ma.ErrProtocolNotFound {
maddrs = append(maddrs, raddr)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going to be racy. We should probably be using a channel and collecting these in a central location.

}
// filter out addresses that still doesn't end in `ipfs/Qm...`
for _, raddr := range raddrs {
if _, err := raddr.ValueForProtocol(ma.P_IPFS); err != ma.ErrProtocolNotFound {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(will need the same "is an IPFS address as the one I suggested above")

@ghost ghost assigned Stebalien Oct 25, 2018
@ghost ghost added the status/in-progress In progress label Oct 25, 2018
@overbool overbool force-pushed the fix/support-for-dnsaddr branch 3 times, most recently from 04a410b to 66be4f4 Compare October 25, 2018 13:33
@overbool
Copy link
Contributor Author

@Stebalien Thx your advice, i had fixed it.

License: MIT
Signed-off-by: Overbool <overbool.xu@gmail.com>
License: MIT
Signed-off-by: Overbool <overbool.xu@gmail.com>
License: MIT
Signed-off-by: Steven Allen <steven@stebalien.com>
License: MIT
Signed-off-by: Steven Allen <steven@stebalien.com>
License: MIT
Signed-off-by: Steven Allen <steven@stebalien.com>
License: MIT
Signed-off-by: Steven Allen <steven@stebalien.com>
@Stebalien Stebalien merged commit 37db5be into ipfs:master Mar 19, 2019
@ghost ghost removed the status/in-progress In progress label Mar 19, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants