-
Notifications
You must be signed in to change notification settings - Fork 5.5k
apple dns: resolve IP addresses without calling Apple APIs #13698
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
Changes from 4 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -113,22 +113,55 @@ ActiveDnsQuery* AppleDnsResolverImpl::resolve(const std::string& dns_name, | |
| DnsLookupFamily dns_lookup_family, | ||
| ResolveCb callback) { | ||
| ENVOY_LOG(debug, "DNS resolver resolve={}", dns_name); | ||
| std::unique_ptr<PendingResolution> pending_resolution( | ||
| new PendingResolution(*this, callback, dispatcher_, main_sd_ref_, dns_name)); | ||
|
|
||
| DNSServiceErrorType error = pending_resolution->dnsServiceGetAddrInfo(dns_lookup_family); | ||
| if (error != kDNSServiceErr_NoError) { | ||
| ENVOY_LOG(warn, "DNS resolver error ({}) in dnsServiceGetAddrInfo for {}", error, dns_name); | ||
| return nullptr; | ||
| Address::InstanceConstSharedPtr address{}; | ||
| try { | ||
| // After production testing with this resolver implementation it became empirically demonstrable | ||
| // that Apple's API issues queries to the DNS server for dns_name that might already be an IP | ||
| // address. In contrast, c-ares synchronously resolves such cases. Moreover, some DNS servers | ||
| // might not resolve IP addresses and thus result in callback targets that never get a | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think phrasing it this way is a little bit backwards. Even if we have an example of a DNS server that does "resolve" an IP address, I wouldn't bet on this being standard or expected. I think this comment can probably be truncated to something along the lines of, "When an IP address is submitted to c-ares it synchronously returns it without submitting a DNS query. Because we've come to rely on this behavior, this resolver implements a similar resolution path to avoid making improper DNS queries for resolved IPs." |
||
| // resolution. Therefore, we short circuit here by trying to parse the dns_name into an internet | ||
| // address and synchronously issue the ResolveCb; only if the parsing throws an exception the | ||
| // resolver issues a call to Apple's API. | ||
| address = Utility::parseInternetAddress(dns_name); | ||
| ENVOY_LOG(debug, "DNS resolver resolved ({}) to ({}) without issuing call to Apple API", | ||
| dns_name, address->asString()); | ||
| } catch (const EnvoyException& e) { | ||
| // Resolution via Apple APIs | ||
| ENVOY_LOG(debug, "DNS resolver local resolution failed with: {}", e.what()); | ||
| std::unique_ptr<PendingResolution> pending_resolution( | ||
| new PendingResolution(*this, callback, dispatcher_, main_sd_ref_, dns_name)); | ||
|
|
||
| DNSServiceErrorType error = pending_resolution->dnsServiceGetAddrInfo(dns_lookup_family); | ||
| if (error != kDNSServiceErr_NoError) { | ||
| ENVOY_LOG(warn, "DNS resolver error ({}) in dnsServiceGetAddrInfo for {}", error, dns_name); | ||
| return nullptr; | ||
| } | ||
|
|
||
| // If the query was synchronously resolved in the Apple API call, there is no need to return the | ||
| // query. | ||
| if (pending_resolution->synchronously_completed_) { | ||
| return nullptr; | ||
| } | ||
|
|
||
| pending_resolution->owned_ = true; | ||
| return pending_resolution.release(); | ||
| } | ||
|
|
||
| // If the query was synchronously resolved, there is no need to return the query. | ||
| if (pending_resolution->synchronously_completed_) { | ||
| ASSERT(address != nullptr); | ||
| // Finish local, synchronous resolution. This needs to happen outside of the exception block above | ||
| // as the callback itself can throw. | ||
| try { | ||
| callback(DnsResolver::ResolutionStatus::Success, | ||
| {DnsResponse(address, std::chrono::seconds(60))}); | ||
| return nullptr; | ||
| } catch (const std::exception& e) { | ||
| ENVOY_LOG(warn, "std::exception in callback with local resolution: {}", e.what()); | ||
| throw EnvoyException(e.what()); | ||
| } catch (...) { | ||
| ENVOY_LOG(warn, "Unknown exception in callback with local resolution"); | ||
| throw EnvoyException("unknown"); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this try catch needed vs. just letting the callback through if that is what it does?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was imitating the c-ares resolver which catches other exception types and throws them as EnvoyExceptions (plus post the throw). But, yeah if we don't mind about the exception type I can just call the callback without the try.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given that we are calling code we own, I don't know why we would be catching other types and wrapping them, so I would just remove all of this. |
||
| } | ||
|
|
||
| pending_resolution->owned_ = true; | ||
| return pending_resolution.release(); | ||
| } | ||
|
|
||
| void AppleDnsResolverImpl::addPendingQuery(PendingResolution* query) { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.