1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
// HostnameLookup.cpp
// Implements the cHostnameLookup class representing an in-progress hostname-to-IP lookup
#include "Globals.h"
#include "HostnameLookup.h"
#include "NetworkSingleton.h"
#include "GetAddressInfoError.h"
////////////////////////////////////////////////////////////////////////////////
// cHostnameLookup:
void cHostnameLookup::Lookup(
const AString & a_Hostname, cNetwork::cResolveNameCallbacksPtr a_Callbacks)
{
// Note the Lookup object is owned solely by this lambda which is destroyed
// after it runs
cNetworkSingleton::Get().GetLookupThread().async_resolve(
a_Hostname, "",
[Callbacks = std::move(a_Callbacks)](const auto & a_Error, const auto & a_Results)
{
// If an error has occurred, notify the error callback:
if (a_Error)
{
Callbacks->OnError(a_Error.value(), a_Error.message());
return;
}
Callback(*Callbacks.get(), a_Results);
}
);
}
void cHostnameLookup::Callback(cNetwork::cResolveNameCallbacks & a_Callbacks, const asio::ip::tcp::resolver::results_type & a_Addr)
{
// Call the success handler for each entry received:
bool HasResolved = false;
for (const auto & Addr : a_Addr)
{
const auto & Endpoint = Addr.endpoint();
const auto & Address = Endpoint.address();
const auto & Hostname = Addr.host_name();
if (Address.is_v4())
{
const auto sin =
reinterpret_cast<const sockaddr_in *>(Endpoint.data());
if (!a_Callbacks.OnNameResolvedV4(Hostname, sin))
{
// Callback indicated that the IP shouldn't be serialized to
// a string, just continue with the next address:
HasResolved = true;
continue;
}
}
else if (Address.is_v6())
{
const auto sin =
reinterpret_cast<const sockaddr_in6 *>(Endpoint.data());
if (!a_Callbacks.OnNameResolvedV6(Hostname, sin))
{
// Callback indicated that the IP shouldn't be serialized to
// a string, just continue with the next address:
HasResolved = true;
continue;
}
}
else
{
// Unknown address family, handle as if this entry wasn't
// received
continue; // for (a_Addr)
}
a_Callbacks.OnNameResolved(Hostname, Address.to_string());
HasResolved = true;
} // for (a_Addr)
// If only unsupported families were reported, call the Error handler:
if (!HasResolved)
{
a_Callbacks.OnError(EAI_NONAME, ErrorString(EAI_NONAME));
}
else
{
a_Callbacks.OnFinished();
}
}
////////////////////////////////////////////////////////////////////////////////
// cNetwork API:
bool cNetwork::HostnameToIP(
const AString & a_Hostname,
cNetwork::cResolveNameCallbacksPtr a_Callbacks
)
{
cHostnameLookup::Lookup(a_Hostname, std::move(a_Callbacks));
return true;
}
|