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
|
/*
* Copyright (C) 2005-2018 Team Kodi
* This file is part of Kodi - https://kodi.tv
*
* SPDX-License-Identifier: GPL-2.0-or-later
* See LICENSES/README.md for more information.
*/
#include "DNSNameCache.h"
#include "threads/CriticalSection.h"
#include "utils/StringUtils.h"
#include "utils/log.h"
#include <mutex>
#if !defined(TARGET_WINDOWS) && defined(HAS_FILESYSTEM_SMB)
#include "ServiceBroker.h"
#include "platform/posix/filesystem/SMBWSDiscovery.h"
#endif
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
CDNSNameCache g_DNSCache;
CCriticalSection CDNSNameCache::m_critical;
CDNSNameCache::CDNSNameCache(void) = default;
CDNSNameCache::~CDNSNameCache(void) = default;
bool CDNSNameCache::Lookup(const std::string& strHostName, std::string& strIpAddress)
{
if (strHostName.empty() && strIpAddress.empty())
return false;
// first see if this is already an ip address
unsigned long address = inet_addr(strHostName.c_str());
strIpAddress.clear();
if (address != INADDR_NONE)
{
strIpAddress = StringUtils::Format("{}.{}.{}.{}", (address & 0xFF), (address & 0xFF00) >> 8,
(address & 0xFF0000) >> 16, (address & 0xFF000000) >> 24);
return true;
}
// check if there's a custom entry or if it's already cached
if(g_DNSCache.GetCached(strHostName, strIpAddress))
return true;
// perform dns lookup
struct hostent *host = gethostbyname(strHostName.c_str());
if (host && host->h_addr_list[0])
{
strIpAddress = StringUtils::Format("{}.{}.{}.{}", (unsigned char)host->h_addr_list[0][0],
(unsigned char)host->h_addr_list[0][1],
(unsigned char)host->h_addr_list[0][2],
(unsigned char)host->h_addr_list[0][3]);
g_DNSCache.Add(strHostName, strIpAddress);
return true;
}
CLog::Log(LOGERROR, "Unable to lookup host: '{}'", strHostName);
return false;
}
bool CDNSNameCache::GetCached(const std::string& strHostName, std::string& strIpAddress)
{
{
std::unique_lock<CCriticalSection> lock(m_critical);
// loop through all DNSname entries and see if strHostName is cached
for (const auto& DNSname : g_DNSCache.m_vecDNSNames)
{
if (DNSname.m_strHostName == strHostName)
{
strIpAddress = DNSname.m_strIpAddress;
return true;
}
}
}
#if !defined(TARGET_WINDOWS) && defined(HAS_FILESYSTEM_SMB)
if (WSDiscovery::CWSDiscoveryPosix::IsInitialized())
{
WSDiscovery::CWSDiscoveryPosix& WSInstance =
dynamic_cast<WSDiscovery::CWSDiscoveryPosix&>(CServiceBroker::GetWSDiscovery());
if (WSInstance.GetCached(strHostName, strIpAddress))
return true;
}
else
CLog::Log(LOGDEBUG, LOGWSDISCOVERY,
"CDNSNameCache::GetCached: CWSDiscoveryPosix not initialized");
#endif
// not cached
return false;
}
void CDNSNameCache::Add(const std::string& strHostName, const std::string& strIpAddress)
{
CDNSName dnsName;
dnsName.m_strHostName = strHostName;
dnsName.m_strIpAddress = strIpAddress;
std::unique_lock<CCriticalSection> lock(m_critical);
g_DNSCache.m_vecDNSNames.push_back(dnsName);
}
|