forked from fusion32/tibia-querymanager
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhostcache.cc
More file actions
107 lines (93 loc) · 2.7 KB
/
hostcache.cc
File metadata and controls
107 lines (93 loc) · 2.7 KB
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
#include "querymanager.hh"
// TODO(fusion): Support windows eventually?
#if OS_LINUX
# include <netdb.h>
#else
# error "Operating system not currently supported."
#endif
struct THostCacheEntry{
char HostName[100];
bool Resolved;
int IPAddress;
int ResolveTime;
};
static THostCacheEntry *g_CachedHostNames;
bool InitHostCache(void){
ASSERT(g_CachedHostNames == NULL);
g_CachedHostNames = (THostCacheEntry*)calloc(
g_Config.MaxCachedHostNames, sizeof(THostCacheEntry));
return true;
}
void ExitHostCache(void){
if(g_CachedHostNames != NULL){
free(g_CachedHostNames);
g_CachedHostNames = NULL;
}
}
static bool DoResolveHostName(const char *HostName, int *OutAddr){
ASSERT(HostName != NULL && OutAddr != NULL);
addrinfo *Result = NULL;
addrinfo Hints = {};
Hints.ai_family = AF_INET;
Hints.ai_socktype = SOCK_STREAM;
int ErrorCode = getaddrinfo(HostName, NULL, &Hints, &Result);
if(ErrorCode != 0){
LOG_ERR("Failed to resolve hostname \"%s\": %s", HostName, gai_strerror(ErrorCode));
return false;
}
bool Resolved = false;
for(addrinfo *AddrInfo = Result;
AddrInfo != NULL;
AddrInfo = AddrInfo->ai_next){
if(AddrInfo->ai_family == AF_INET && AddrInfo->ai_socktype == SOCK_STREAM){
ASSERT(AddrInfo->ai_addrlen == sizeof(sockaddr_in));
*OutAddr = ntohl(((sockaddr_in*)AddrInfo->ai_addr)->sin_addr.s_addr);
Resolved = true;
break;
}
}
freeaddrinfo(Result);
return Resolved;
}
bool ResolveHostName(const char *HostName, int *OutAddr){
if(HostName == NULL || StringEmpty(HostName)){
return false;
}
THostCacheEntry *Entry = NULL;
int LeastRecentlyUsedIndex = 0;
int LeastRecentlyUsedTime = g_CachedHostNames[0].ResolveTime;
int TimeNow = GetMonotonicUptime();
for(int i = 0; i < g_Config.MaxCachedHostNames; i += 1){
THostCacheEntry *Current = &g_CachedHostNames[i];
if((TimeNow - Current->ResolveTime) >= g_Config.HostNameExpireTime){
memset(Current, 0, sizeof(THostCacheEntry));
}
if(Current->ResolveTime < LeastRecentlyUsedTime){
LeastRecentlyUsedIndex = i;
LeastRecentlyUsedTime = Current->ResolveTime;
}
if(StringEq(HostName, Current->HostName)){
Entry = Current;
break;
}
}
if(Entry == NULL){
// NOTE(fusion): We also cache failures.
Entry = &g_CachedHostNames[LeastRecentlyUsedIndex];
if(!StringBufCopy(Entry->HostName, HostName)){
LOG_WARN("Hostname \"%s\" was improperly cached because it was"
" too long (Length: %d, MaxLength: %d)", HostName,
(int)strlen(HostName), (int)sizeof(Entry->HostName));
}
Entry->Resolved = DoResolveHostName(HostName, &Entry->IPAddress);
Entry->ResolveTime = TimeNow;
}
if(Entry && Entry->Resolved){
if(OutAddr){
*OutAddr = Entry->IPAddress;
}
return true;
}else{
return false;
}
}