Add DNS cache.

This commit is contained in:
Renxuan Wang 2022-04-03 17:33:18 -07:00
parent ff934ca2ad
commit e548c0d604
5 changed files with 99 additions and 18 deletions

View File

@ -131,7 +131,8 @@ UID SimExternalConnection::getDebugID() const {
}
std::vector<NetworkAddress> SimExternalConnection::resolveTCPEndpointBlocking(const std::string& host,
const std::string& service) {
const std::string& service,
DNSCache* dnsCache) {
ip::tcp::resolver resolver(ios);
try {
auto iter = resolver.resolve(host, service);
@ -147,20 +148,28 @@ std::vector<NetworkAddress> SimExternalConnection::resolveTCPEndpointBlocking(co
}
++iter;
}
if (addrs.empty()) {
throw lookup_failed();
}
dnsCache->add(host, service, addrs);
return addrs;
} catch (...) {
dnsCache->remove(host, service);
throw lookup_failed();
}
}
ACTOR static Future<std::vector<NetworkAddress>> resolveTCPEndpointImpl(std::string host, std::string service) {
ACTOR static Future<std::vector<NetworkAddress>> resolveTCPEndpointImpl(std::string host,
std::string service,
DNSCache* dnsCache) {
wait(delayJittered(0.1));
return SimExternalConnection::resolveTCPEndpointBlocking(host, service);
return SimExternalConnection::resolveTCPEndpointBlocking(host, service, dnsCache);
}
Future<std::vector<NetworkAddress>> SimExternalConnection::resolveTCPEndpoint(const std::string& host,
const std::string& service) {
return resolveTCPEndpointImpl(host, service);
const std::string& service,
DNSCache* dnsCache) {
return resolveTCPEndpointImpl(host, service, dnsCache);
}
Future<Reference<IConnection>> SimExternalConnection::connect(NetworkAddress toAddr) {

View File

@ -48,8 +48,12 @@ public:
int write(SendBuffer const* buffer, int limit) override;
NetworkAddress getPeerAddress() const override;
UID getDebugID() const override;
static Future<std::vector<NetworkAddress>> resolveTCPEndpoint(const std::string& host, const std::string& service);
static std::vector<NetworkAddress> resolveTCPEndpointBlocking(const std::string& host, const std::string& service);
static Future<std::vector<NetworkAddress>> resolveTCPEndpoint(const std::string& host,
const std::string& service,
DNSCache* dnsCache);
static std::vector<NetworkAddress> resolveTCPEndpointBlocking(const std::string& host,
const std::string& service,
DNSCache* dnsCache);
static Future<Reference<IConnection>> connect(NetworkAddress toAddr);
};

View File

@ -981,7 +981,20 @@ public:
if (mock.present()) {
return mock.get();
}
return SimExternalConnection::resolveTCPEndpoint(host, service);
return SimExternalConnection::resolveTCPEndpoint(host, service, &dnsCache);
}
Future<std::vector<NetworkAddress>> resolveTCPEndpointWithDNSCache(const std::string& host,
const std::string& service) override {
// If a <hostname, vector<NetworkAddress>> pair was injected to mock DNS, use it.
Optional<std::vector<NetworkAddress>> mock = mockDNS.find(host, service);
if (mock.present()) {
return mock.get();
}
Optional<std::vector<NetworkAddress>> cache = dnsCache.find(host, service);
if (cache.present()) {
return cache.get();
}
return SimExternalConnection::resolveTCPEndpoint(host, service, &dnsCache);
}
std::vector<NetworkAddress> resolveTCPEndpointBlocking(const std::string& host,
const std::string& service) override {
@ -990,7 +1003,20 @@ public:
if (mock.present()) {
return mock.get();
}
return SimExternalConnection::resolveTCPEndpointBlocking(host, service);
return SimExternalConnection::resolveTCPEndpointBlocking(host, service, &dnsCache);
}
std::vector<NetworkAddress> resolveTCPEndpointBlockingWithDNSCache(const std::string& host,
const std::string& service) override {
// If a <hostname, vector<NetworkAddress>> pair was injected to mock DNS, use it.
Optional<std::vector<NetworkAddress>> mock = mockDNS.find(host, service);
if (mock.present()) {
return mock.get();
}
Optional<std::vector<NetworkAddress>> cache = dnsCache.find(host, service);
if (cache.present()) {
return cache.get();
}
return SimExternalConnection::resolveTCPEndpointBlocking(host, service, &dnsCache);
}
ACTOR static Future<Reference<IConnection>> onConnect(Future<Void> ready, Reference<Sim2Conn> conn) {
wait(ready);

View File

@ -166,8 +166,12 @@ public:
Future<std::vector<NetworkAddress>> resolveTCPEndpoint(const std::string& host,
const std::string& service) override;
Future<std::vector<NetworkAddress>> resolveTCPEndpointWithDNSCache(const std::string& host,
const std::string& service) override;
std::vector<NetworkAddress> resolveTCPEndpointBlocking(const std::string& host,
const std::string& service) override;
std::vector<NetworkAddress> resolveTCPEndpointBlockingWithDNSCache(const std::string& host,
const std::string& service) override;
Reference<IListener> listen(NetworkAddress localAddr) override;
// INetwork interface
@ -1837,6 +1841,14 @@ Future<Reference<IConnection>> Net2::connectExternal(NetworkAddress toAddr, cons
return connect(toAddr, host);
}
Future<Reference<IUDPSocket>> Net2::createUDPSocket(NetworkAddress toAddr) {
return UDPSocket::connect(&reactor.ios, toAddr, toAddr.ip.isV6());
}
Future<Reference<IUDPSocket>> Net2::createUDPSocket(bool isV6) {
return UDPSocket::connect(&reactor.ios, Optional<NetworkAddress>(), isV6);
}
ACTOR static Future<std::vector<NetworkAddress>> resolveTCPEndpoint_impl(Net2* self,
std::string host,
std::string service) {
@ -1847,6 +1859,7 @@ ACTOR static Future<std::vector<NetworkAddress>> resolveTCPEndpoint_impl(Net2* s
tcpResolver.async_resolve(tcp::resolver::query(host, service),
[=](const boost::system::error_code& ec, tcp::resolver::iterator iter) {
if (ec) {
self->dnsCache.remove(host, service);
promise.sendError(lookup_failed());
return;
}
@ -1866,6 +1879,7 @@ ACTOR static Future<std::vector<NetworkAddress>> resolveTCPEndpoint_impl(Net2* s
}
if (addrs.empty()) {
self->dnsCache.remove(host, service);
promise.sendError(lookup_failed());
} else {
promise.send(addrs);
@ -1874,22 +1888,25 @@ ACTOR static Future<std::vector<NetworkAddress>> resolveTCPEndpoint_impl(Net2* s
wait(ready(result));
tcpResolver.cancel();
std::vector<NetworkAddress> ret = result.get();
self->dnsCache.add(host, service, ret);
return result.get();
}
Future<Reference<IUDPSocket>> Net2::createUDPSocket(NetworkAddress toAddr) {
return UDPSocket::connect(&reactor.ios, toAddr, toAddr.ip.isV6());
}
Future<Reference<IUDPSocket>> Net2::createUDPSocket(bool isV6) {
return UDPSocket::connect(&reactor.ios, Optional<NetworkAddress>(), isV6);
return ret;
}
Future<std::vector<NetworkAddress>> Net2::resolveTCPEndpoint(const std::string& host, const std::string& service) {
return resolveTCPEndpoint_impl(this, host, service);
}
Future<std::vector<NetworkAddress>> Net2::resolveTCPEndpointWithDNSCache(const std::string& host,
const std::string& service) {
Optional<std::vector<NetworkAddress>> cache = dnsCache.find(host, service);
if (cache.present()) {
return cache.get();
}
return resolveTCPEndpoint_impl(this, host, service);
}
std::vector<NetworkAddress> Net2::resolveTCPEndpointBlocking(const std::string& host, const std::string& service) {
tcp::resolver tcpResolver(reactor.ios);
try {
@ -1906,12 +1923,25 @@ std::vector<NetworkAddress> Net2::resolveTCPEndpointBlocking(const std::string&
}
++iter;
}
if (addrs.empty()) {
throw lookup_failed();
}
return addrs;
} catch (...) {
dnsCache.remove(host, service);
throw lookup_failed();
}
}
std::vector<NetworkAddress> Net2::resolveTCPEndpointBlockingWithDNSCache(const std::string& host,
const std::string& service) {
Optional<std::vector<NetworkAddress>> cache = dnsCache.find(host, service);
if (cache.present()) {
return cache.get();
}
return resolveTCPEndpointBlocking(host, service);
}
bool Net2::isAddressOnThisHost(NetworkAddress const& addr) const {
auto it = addressOnHostCache.find(addr.ip);
if (it != addressOnHostCache.end())

View File

@ -745,10 +745,17 @@ public:
// NetworkAddresses
virtual Future<std::vector<NetworkAddress>> resolveTCPEndpoint(const std::string& host,
const std::string& service) = 0;
// Similar to resolveTCPEndpoint(), except that this one uses DNS cache.
virtual Future<std::vector<NetworkAddress>> resolveTCPEndpointWithDNSCache(const std::string& host,
const std::string& service) = 0;
// Resolve host name and service name. This one should only be used when resolving asynchronously is impossible. For
// all other cases, resolveTCPEndpoint() should be preferred.
virtual std::vector<NetworkAddress> resolveTCPEndpointBlocking(const std::string& host,
const std::string& service) = 0;
// Resolve host name and service name with DNS cache. This one should only be used when resolving asynchronously is
// impossible. For all other cases, resolveTCPEndpointWithDNSCache() should be preferred.
virtual std::vector<NetworkAddress> resolveTCPEndpointBlockingWithDNSCache(const std::string& host,
const std::string& service) = 0;
// Convenience function to resolve host/service and connect to one of its NetworkAddresses randomly
// isTLS has to be a parameter here because it is passed to connect() as part of the toAddr object.
@ -762,6 +769,11 @@ public:
static INetworkConnections* net() {
return static_cast<INetworkConnections*>((void*)g_network->global(INetwork::enNetworkConnections));
}
void removeCachedDNS(const std::string& host, const std::string& service) { dnsCache.remove(host, service); }
DNSCache dnsCache;
// Returns the interface that should be used to make and accept socket connections
};