Skip to content

Apply the Happy Eyeballs philosophy to parallel c-ares queries - #3699

Closed
b-spencer wants to merge 4 commits into
curl:masterfrom
b-spencer:submit.happy-eyeballs-dns
Closed

Apply the Happy Eyeballs philosophy to parallel c-ares queries#3699
b-spencer wants to merge 4 commits into
curl:masterfrom
b-spencer:submit.happy-eyeballs-dns

Conversation

@b-spencer

Copy link
Copy Markdown

When it supports both IPv4 and IPv6, cURL follows the happy eyeballs algorithm by trying to connect via both protocols in a staggered fashion. When cURL is configured to use c-ares, this also means doing two simultaneous, parallel DNS requests, one for the A record and one for the AAAA record, so that cURL can have both the IPv4 and IPv6 address in hand. (Ideally, there'd be a single request, but that's not the case for a variety of reasons.)

Today, cURL issues both of these requests at the same time, which is good. However, this parallelism is encapsulated within the c-ares driver, so the larger cURL logic is unaware that there are actually two requests and not just a single (combined A and AAAA) DNS request. The rest of cURL waits for this meta request to finish before it tries to start any connections.

Unfortunately, when either one of the parallel c-ares requests takes a long time to finish, cURL sits and waits for it, even if the c-ares driver does have a viable DNS result from the other request. Practically speaking, this means that if you are on a network that claims to support IPv6 and allows binding such sockets and addresses locally, but whose DNS server is misconfigured and can't properly respond to AAAA requests, you can find yourself in a situation where you have the usable A record in hand, but you're waiting for a series of timeouts and/or failures from all the malfunctioning DNS servers in the list.

This PR makes a small tweak to the existing c-ares driver that takes same "happy eyeballs" philosophy from the actual TCP connections (connect to one and then after a short timeout, try the other) and it applies it to the parallel DNS requests themselves. With this change, once a usable DNS response is in hand (be it A or AAAA), c-ares will only wait a short time before giving up on the second response and just going with what it has.

The exact algorithm and rationale are documented in the comments inside the PR. The changes were specifically chosen to be simple and not overly aggressive. This might not be the best "fix", but it seems better than the status quo, and I hope that it can at least be the start of a discussion on how to handle real-world cases like this.

@bagder bagder left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sounds like an excellent idea and approach!

@bagder

bagder commented Mar 24, 2019

Copy link
Copy Markdown
Member

the only test fail is the libssh2 test failure which is unrelated (but I don't know why it started fail in all CI builds...)

@bagder bagder added feature-window A merge of this requires an open feature window name lookup DNS and related tech labels Mar 24, 2019
@bagder

bagder commented Mar 24, 2019

Copy link
Copy Markdown
Member

Just to play this safe as there's a release coming in just a few days, I want to merge this after the pending release to give this slightly more time to cook before it ships.

Comment thread lib/asyn-ares.c
/* How long we are willing to wait for additional parallel responses after
obtaining a "definitive" one.

This is intended to equal the c-ares default timeout. cURL always uses that

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This should be "curl", but that nitpick can be fixed by the committer rather than require a fresh rebase IMHO.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Oops. I've been spelling it what I guess is the old-fashioned way!

Thanks!

BTW, maybe someone should fix the Wikipedia article's spelling :)

@bagder

bagder commented Mar 27, 2019

Copy link
Copy Markdown
Member

Thanks!

@bagder bagder closed this in 80208d6 Mar 27, 2019
@lock lock Bot locked as resolved and limited conversation to collaborators Jun 26, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

feature-window A merge of this requires an open feature window name lookup DNS and related tech

Development

Successfully merging this pull request may close these issues.

3 participants