Skip to content

Commit 05934ab

Browse files
authored
Support returning multiple results for dns parsing (#265)
1 parent 8601bb9 commit 05934ab

File tree

5 files changed

+108
-25
lines changed

5 files changed

+108
-25
lines changed

trantor/net/Resolver.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ class TRANTOR_EXPORT Resolver
2222
{
2323
public:
2424
using Callback = std::function<void(const trantor::InetAddress&)>;
25+
using ResolverResultsCallback =
26+
std::function<void(const std::vector<trantor::InetAddress>&)>;
2527

2628
/**
2729
* @brief Create a new DNS resolver.
@@ -42,6 +44,15 @@ class TRANTOR_EXPORT Resolver
4244
virtual void resolve(const std::string& hostname,
4345
const Callback& callback) = 0;
4446

47+
/**
48+
* @brief Resolve an address array asynchronously.
49+
*
50+
* @param hostname
51+
* @param callback
52+
*/
53+
virtual void resolve(const std::string& hostname,
54+
const ResolverResultsCallback& callback) = 0;
55+
4556
virtual ~Resolver()
4657
{
4758
}

trantor/net/inner/AresResolver.cc

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,14 @@ AresResolver::~AresResolver()
110110
}
111111

112112
void AresResolver::resolveInLoop(const std::string& hostname,
113-
const Callback& cb)
113+
const ResolverResultsCallback& cb)
114114
{
115115
loop_->assertInLoopThread();
116116
#ifdef _WIN32
117117
if (hostname == "localhost")
118118
{
119-
const static trantor::InetAddress localhost_{"127.0.0.1", 0};
119+
const static std::vector<trantor::InetAddress> localhost_{
120+
trantor::InetAddress{"127.0.0.1", 0}};
120121
cb(localhost_);
121122
return;
122123
}
@@ -167,25 +168,39 @@ void AresResolver::onTimer()
167168
void AresResolver::onQueryResult(int status,
168169
struct hostent* result,
169170
const std::string& hostname,
170-
const Callback& callback)
171+
const ResolverResultsCallback& callback)
171172
{
172173
LOG_TRACE << "onQueryResult " << status;
173-
struct sockaddr_in addr;
174-
memset(&addr, 0, sizeof addr);
175-
addr.sin_family = AF_INET;
176-
addr.sin_port = 0;
174+
std::vector<trantor::InetAddress> inets;
177175
if (result)
178176
{
179-
addr.sin_addr = *reinterpret_cast<in_addr*>(result->h_addr);
177+
auto pptr = (struct in_addr**)result->h_addr_list;
178+
for (; *pptr != nullptr; pptr++)
179+
{
180+
struct sockaddr_in addr;
181+
memset(&addr, 0, sizeof addr);
182+
addr.sin_family = AF_INET;
183+
addr.sin_port = 0;
184+
addr.sin_addr = *reinterpret_cast<in_addr*>(*pptr);
185+
inets.emplace_back(trantor::InetAddress{addr});
186+
}
187+
}
188+
if (inets.empty())
189+
{
190+
struct sockaddr_in addr;
191+
memset(&addr, 0, sizeof addr);
192+
addr.sin_family = AF_INET;
193+
addr.sin_port = 0;
194+
InetAddress inet(addr);
195+
inets.emplace_back(std::move(inet));
180196
}
181-
InetAddress inet(addr);
182197
{
183198
std::lock_guard<std::mutex> lock(globalMutex());
184199
auto& addrItem = globalCache()[hostname];
185-
addrItem.first = addr.sin_addr;
200+
addrItem.first = inets;
186201
addrItem.second = trantor::Date::date();
187202
}
188-
callback(inet);
203+
callback(inets);
189204
}
190205

191206
void AresResolver::onSockCreate(int sockfd, int type)

trantor/net/inner/AresResolver.h

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,7 @@ class AresResolver : public Resolver,
4343
if (timeout_ == 0 ||
4444
cachedAddr.second.after(timeout_) > trantor::Date::date())
4545
{
46-
struct sockaddr_in addr;
47-
memset(&addr, 0, sizeof addr);
48-
addr.sin_family = AF_INET;
49-
addr.sin_port = 0;
50-
addr.sin_addr = cachedAddr.first;
51-
inet = InetAddress(addr);
46+
inet = (cachedAddr.first)[0];
5247
cached = true;
5348
}
5449
}
@@ -59,6 +54,49 @@ class AresResolver : public Resolver,
5954
return;
6055
}
6156
if (loop_->isInLoopThread())
57+
{
58+
resolveInLoop(hostname,
59+
[cb](const std::vector<trantor::InetAddress>& inets) {
60+
cb(inets[0]);
61+
});
62+
}
63+
else
64+
{
65+
loop_->queueInLoop([thisPtr = shared_from_this(), hostname, cb]() {
66+
thisPtr->resolveInLoop(
67+
hostname,
68+
[cb](const std::vector<trantor::InetAddress>& inets) {
69+
cb(inets[0]);
70+
});
71+
});
72+
}
73+
}
74+
75+
virtual void resolve(const std::string& hostname,
76+
const ResolverResultsCallback& cb) override
77+
{
78+
bool cached = false;
79+
std::vector<trantor::InetAddress> inets;
80+
{
81+
std::lock_guard<std::mutex> lock(globalMutex());
82+
auto iter = globalCache().find(hostname);
83+
if (iter != globalCache().end())
84+
{
85+
auto& cachedAddr = iter->second;
86+
if (timeout_ == 0 ||
87+
cachedAddr.second.after(timeout_) > trantor::Date::date())
88+
{
89+
inets = cachedAddr.first;
90+
cached = true;
91+
}
92+
}
93+
}
94+
if (cached)
95+
{
96+
cb(inets);
97+
return;
98+
}
99+
if (loop_->isInLoopThread())
62100
{
63101
resolveInLoop(hostname, cb);
64102
}
@@ -74,29 +112,32 @@ class AresResolver : public Resolver,
74112
struct QueryData
75113
{
76114
AresResolver* owner_;
77-
Callback callback_;
115+
ResolverResultsCallback callback_;
78116
std::string hostname_;
79117
QueryData(AresResolver* o,
80-
const Callback& cb,
118+
const ResolverResultsCallback& cb,
81119
const std::string& hostname)
82120
: owner_(o), callback_(cb), hostname_(hostname)
83121
{
84122
}
85123
};
86-
void resolveInLoop(const std::string& hostname, const Callback& cb);
124+
void resolveInLoop(const std::string& hostname,
125+
const ResolverResultsCallback& cb);
87126
void init();
88127
trantor::EventLoop* loop_;
89128
std::shared_ptr<bool> loopValid_;
90129
ares_channel ctx_{nullptr};
91130
bool timerActive_{false};
92131
using ChannelList = std::map<int, std::unique_ptr<trantor::Channel>>;
93132
ChannelList channels_;
94-
static std::unordered_map<std::string,
95-
std::pair<struct in_addr, trantor::Date>>&
133+
static std::unordered_map<
134+
std::string,
135+
std::pair<std::vector<InetAddress>, trantor::Date>>&
96136
globalCache()
97137
{
98-
static std::unordered_map<std::string,
99-
std::pair<struct in_addr, trantor::Date>>
138+
static std::unordered_map<
139+
std::string,
140+
std::pair<std::vector<InetAddress>, trantor::Date>>
100141
dnsCache;
101142
return dnsCache;
102143
}
@@ -118,7 +159,7 @@ class AresResolver : public Resolver,
118159
void onQueryResult(int status,
119160
struct hostent* result,
120161
const std::string& hostname,
121-
const Callback& callback);
162+
const ResolverResultsCallback& callback);
122163
void onSockCreate(int sockfd, int type);
123164
void onSockStateChange(int sockfd, bool read, bool write);
124165

trantor/net/inner/NormalResolver.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ class NormalResolver : public Resolver,
2323
public:
2424
virtual void resolve(const std::string& hostname,
2525
const Callback& callback) override;
26+
virtual void resolve(const std::string& hostname,
27+
const ResolverResultsCallback& callback) override
28+
{
29+
resolve(hostname, [callback](const trantor::InetAddress& inet) {
30+
callback(std::vector<trantor::InetAddress>{inet});
31+
});
32+
}
2633
explicit NormalResolver(size_t timeout)
2734
: timeout_(timeout), resolveBuffer_(kResolveBufferLength)
2835
{

trantor/tests/DnsTest.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@ void dns(const std::shared_ptr<trantor::Resolver> &resolver)
99
std::cout << "baidu:" << addr.toIp() << " " << interval / 1000 << "ms"
1010
<< std::endl;
1111
});
12+
resolver->resolve("www.baidu.com",
13+
[now](const std::vector<trantor::InetAddress> &addrs) {
14+
auto interval =
15+
trantor::Date::now().microSecondsSinceEpoch() -
16+
now.microSecondsSinceEpoch();
17+
for (auto &addr : addrs)
18+
std::cout << "baidu:" << addr.toIp() << " "
19+
<< interval / 1000 << "ms" << std::endl;
20+
});
1221
resolver->resolve("www.google.com",
1322
[now](const trantor::InetAddress &addr) {
1423
auto interval =

0 commit comments

Comments
 (0)