@aws-sdk/util-dns 3.972.16 → 3.972.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cjs/index.js +266 -3
- package/package.json +3 -6
- package/dist-cjs/HostResolver.browser.js +0 -7
- package/dist-cjs/HostResolver.js +0 -2
- package/dist-cjs/NodeDnsLookupHostResolver.js +0 -87
- package/dist-cjs/index.browser.js +0 -2
- package/dist-cjs/util/HostAddressEntryCollection.js +0 -29
- package/dist-cjs/util/HostEntry.js +0 -121
- package/dist-cjs/util/HostEntryTable.js +0 -24
package/dist-cjs/index.js
CHANGED
|
@@ -1,3 +1,266 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
const { HostAddressType } = require("@aws-sdk/types");
|
|
2
|
+
const { promises, V4MAPPED, ALL } = require("dns");
|
|
3
|
+
|
|
4
|
+
class HostAddressEntryCollection {
|
|
5
|
+
data = [];
|
|
6
|
+
get length() {
|
|
7
|
+
return this.data.length;
|
|
8
|
+
}
|
|
9
|
+
cycle(collection) {
|
|
10
|
+
if (this.data.length === 0) {
|
|
11
|
+
throw new Error("Cannot cycle an empty collection");
|
|
12
|
+
}
|
|
13
|
+
const entry = this.data.shift();
|
|
14
|
+
(collection || this).append(entry);
|
|
15
|
+
return entry;
|
|
16
|
+
}
|
|
17
|
+
append(entry) {
|
|
18
|
+
this.data.push(entry);
|
|
19
|
+
}
|
|
20
|
+
remove(entry) {
|
|
21
|
+
if (this.length === 0) {
|
|
22
|
+
throw new Error("Cannot remove from an empty collection");
|
|
23
|
+
}
|
|
24
|
+
const index = this.data.findIndex((e) => e.address === entry.address);
|
|
25
|
+
const removedEntry = this.data[index];
|
|
26
|
+
this.data.splice(index, 1);
|
|
27
|
+
return removedEntry;
|
|
28
|
+
}
|
|
29
|
+
[Symbol.iterator]() {
|
|
30
|
+
return this.data[Symbol.iterator]();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
class HostEntry {
|
|
35
|
+
aaaaRecords;
|
|
36
|
+
aRecords;
|
|
37
|
+
failedAaaaRecords;
|
|
38
|
+
failedARecords;
|
|
39
|
+
nextTimestampToUpdateMs;
|
|
40
|
+
constructor(nextTimestampToProcessMs) {
|
|
41
|
+
this.aaaaRecords = new HostAddressEntryCollection();
|
|
42
|
+
this.aRecords = new HostAddressEntryCollection();
|
|
43
|
+
this.failedAaaaRecords = new HostAddressEntryCollection();
|
|
44
|
+
this.failedARecords = new HostAddressEntryCollection();
|
|
45
|
+
this.nextTimestampToUpdateMs = nextTimestampToProcessMs;
|
|
46
|
+
}
|
|
47
|
+
updateRecords(addresses, expirationTtlMs) {
|
|
48
|
+
this.nextTimestampToUpdateMs = expirationTtlMs;
|
|
49
|
+
const addressesToAppend = [];
|
|
50
|
+
for (const freshAddress of addresses) {
|
|
51
|
+
const hostAddressEntry = this.findAddress(freshAddress);
|
|
52
|
+
if (hostAddressEntry !== undefined) {
|
|
53
|
+
hostAddressEntry.expirationTtlMs = expirationTtlMs;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
addressesToAppend.push(freshAddress);
|
|
57
|
+
}
|
|
58
|
+
for (const addressToAppend of addressesToAppend) {
|
|
59
|
+
const hostAddressEntry = this.findAddress(addressToAppend);
|
|
60
|
+
if (hostAddressEntry !== undefined) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const successRecords = this.getGoodRecords(addressToAppend);
|
|
64
|
+
successRecords.append(Object.assign(addressToAppend, {
|
|
65
|
+
expirationTtlMs,
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
processRecords() {
|
|
70
|
+
this.processRecordsAddressType(this.aRecords, this.failedARecords);
|
|
71
|
+
this.processRecordsAddressType(this.aaaaRecords, this.failedAaaaRecords);
|
|
72
|
+
}
|
|
73
|
+
failAddressInRecords(address) {
|
|
74
|
+
const successRecords = this.getGoodRecords(address);
|
|
75
|
+
const failedRecords = this.getFailedRecords(address);
|
|
76
|
+
const recordsToRemove = [];
|
|
77
|
+
for (const hostAddressEntry of successRecords) {
|
|
78
|
+
if (hostAddressEntry.address === address.address) {
|
|
79
|
+
recordsToRemove.push(hostAddressEntry);
|
|
80
|
+
failedRecords.append(hostAddressEntry);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
for (const recordToRemove of recordsToRemove) {
|
|
84
|
+
successRecords.remove(recordToRemove);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
findAddress(address) {
|
|
88
|
+
const successRecords = this.getGoodRecords(address);
|
|
89
|
+
for (const hostAddressEntry of successRecords) {
|
|
90
|
+
if (address.address === hostAddressEntry.address) {
|
|
91
|
+
return hostAddressEntry;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const failedRecords = this.getFailedRecords(address);
|
|
95
|
+
for (const hostAddressEntry of failedRecords) {
|
|
96
|
+
if (address.address === hostAddressEntry.address) {
|
|
97
|
+
return hostAddressEntry;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
processRecordsAddressType(successRecords, failedRecords) {
|
|
103
|
+
const successRecordsToRemove = [];
|
|
104
|
+
let successIndex = 0;
|
|
105
|
+
for (const hostAddressEntry of successRecords) {
|
|
106
|
+
if (successIndex === successRecords.length - 1) {
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
if (Date.now() >= hostAddressEntry.expirationTtlMs) {
|
|
110
|
+
successRecordsToRemove.push(hostAddressEntry);
|
|
111
|
+
}
|
|
112
|
+
successIndex++;
|
|
113
|
+
}
|
|
114
|
+
for (const recordToRemove of successRecordsToRemove) {
|
|
115
|
+
successRecords.remove(recordToRemove);
|
|
116
|
+
}
|
|
117
|
+
const failedRecordsToRemove = [];
|
|
118
|
+
let failedIndex = 0;
|
|
119
|
+
for (const hostAddressEntry of failedRecords) {
|
|
120
|
+
if (failedIndex === failedRecords.length - 1) {
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
if (Date.now() >= hostAddressEntry.expirationTtlMs) {
|
|
124
|
+
failedRecordsToRemove.push(hostAddressEntry);
|
|
125
|
+
}
|
|
126
|
+
failedIndex++;
|
|
127
|
+
}
|
|
128
|
+
for (const recordToRemove of failedRecordsToRemove) {
|
|
129
|
+
failedRecords.remove(recordToRemove);
|
|
130
|
+
}
|
|
131
|
+
if (successRecords.length === 0) {
|
|
132
|
+
let hostAddressEntryToPromote = undefined;
|
|
133
|
+
for (const hostAddressEntry of failedRecords) {
|
|
134
|
+
if (Date.now() >= hostAddressEntry.expirationTtlMs) {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
hostAddressEntryToPromote = hostAddressEntry;
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
if (hostAddressEntryToPromote !== undefined) {
|
|
141
|
+
failedRecords.remove(hostAddressEntryToPromote);
|
|
142
|
+
successRecords.append(hostAddressEntryToPromote);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
getGoodRecords(address) {
|
|
147
|
+
return address.addressType === HostAddressType.AAAA ? this.aaaaRecords : this.aRecords;
|
|
148
|
+
}
|
|
149
|
+
getFailedRecords(address) {
|
|
150
|
+
return address.addressType === HostAddressType.AAAA ? this.failedAaaaRecords : this.failedARecords;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
class HostEntryTable {
|
|
155
|
+
map;
|
|
156
|
+
constructor() {
|
|
157
|
+
this.map = new Map();
|
|
158
|
+
}
|
|
159
|
+
set(args, addresses, nextTimestampToProcessMs) {
|
|
160
|
+
const hostEntry = new HostEntry(nextTimestampToProcessMs);
|
|
161
|
+
hostEntry.updateRecords(addresses, nextTimestampToProcessMs);
|
|
162
|
+
this.map.set(args.hostName, hostEntry);
|
|
163
|
+
}
|
|
164
|
+
get(hostName) {
|
|
165
|
+
return this.map.get(hostName);
|
|
166
|
+
}
|
|
167
|
+
delete(hostName) {
|
|
168
|
+
this.map.delete(hostName);
|
|
169
|
+
}
|
|
170
|
+
clear() {
|
|
171
|
+
this.map.clear();
|
|
172
|
+
}
|
|
173
|
+
get size() {
|
|
174
|
+
return this.map.size;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const NODE_DNS_FAMILY_TO_HOST_ADDRESS_TYPE = {
|
|
179
|
+
4: HostAddressType.A,
|
|
180
|
+
6: HostAddressType.AAAA,
|
|
181
|
+
};
|
|
182
|
+
const DNS_LOOKUP_OPTIONS = {
|
|
183
|
+
all: true,
|
|
184
|
+
hints: V4MAPPED | ALL,
|
|
185
|
+
verbatim: true,
|
|
186
|
+
};
|
|
187
|
+
class NodeDnsLookupHostResolver {
|
|
188
|
+
static DEFAULT_TTL_MS = 30_000;
|
|
189
|
+
static createDefaultCacheProvider = () => new HostEntryTable();
|
|
190
|
+
static DEFAULT_NODE_DNS_LOOKUP = promises.lookup;
|
|
191
|
+
ttlMs;
|
|
192
|
+
cache;
|
|
193
|
+
nodeDnsLookup;
|
|
194
|
+
constructor({ ttlMs = NodeDnsLookupHostResolver.DEFAULT_TTL_MS, cache = NodeDnsLookupHostResolver.createDefaultCacheProvider(), nodeDnsLookup = NodeDnsLookupHostResolver.DEFAULT_NODE_DNS_LOOKUP, } = {}) {
|
|
195
|
+
this.ttlMs = ttlMs;
|
|
196
|
+
this.cache = cache;
|
|
197
|
+
this.nodeDnsLookup = nodeDnsLookup;
|
|
198
|
+
}
|
|
199
|
+
async resolveAddress(args) {
|
|
200
|
+
const possibleHostEntry = this.cache.get(args.hostName);
|
|
201
|
+
const newNextTimestampToUpdateMs = Date.now() + this.ttlMs;
|
|
202
|
+
if (possibleHostEntry === undefined) {
|
|
203
|
+
const addresses = await this.nodeDnsLookupResolveAddress(args);
|
|
204
|
+
this.cache.set(args, addresses, newNextTimestampToUpdateMs);
|
|
205
|
+
}
|
|
206
|
+
const hostEntry = this.cache.get(args.hostName);
|
|
207
|
+
if (possibleHostEntry !== undefined && Date.now() >= hostEntry.nextTimestampToUpdateMs) {
|
|
208
|
+
try {
|
|
209
|
+
const addresses = await this.nodeDnsLookupResolveAddress(args);
|
|
210
|
+
hostEntry.updateRecords(addresses, newNextTimestampToUpdateMs);
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
console.error(`Could not update DNS address cache for "${args.hostName}": ${error}`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
hostEntry.processRecords();
|
|
217
|
+
const result = [];
|
|
218
|
+
if (hostEntry.aRecords.length > 0) {
|
|
219
|
+
result.push(hostEntry.aRecords.cycle());
|
|
220
|
+
}
|
|
221
|
+
if (hostEntry.aaaaRecords.length > 0) {
|
|
222
|
+
result.push(hostEntry.aaaaRecords.cycle());
|
|
223
|
+
}
|
|
224
|
+
if (result.length === 0) {
|
|
225
|
+
throw new Error(`Could not resolve addresses for "${args.hostName}"`);
|
|
226
|
+
}
|
|
227
|
+
return result;
|
|
228
|
+
}
|
|
229
|
+
reportFailureOnAddress(addr) {
|
|
230
|
+
const hostEntry = this.cache.get(addr.hostName);
|
|
231
|
+
if (hostEntry === undefined) {
|
|
232
|
+
throw new Error(`Could not find cached host name "${addr.hostName}"`);
|
|
233
|
+
}
|
|
234
|
+
hostEntry.failAddressInRecords(addr);
|
|
235
|
+
}
|
|
236
|
+
purgeCache(args) {
|
|
237
|
+
if (args?.hostName) {
|
|
238
|
+
this.cache.delete(args.hostName);
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
this.cache.clear();
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
async nodeDnsLookupResolveAddress(args) {
|
|
245
|
+
const addresses = [];
|
|
246
|
+
const ipEntries = await this.nodeDnsLookup(args.hostName, DNS_LOOKUP_OPTIONS);
|
|
247
|
+
for (const { address, family } of ipEntries) {
|
|
248
|
+
const addressType = NODE_DNS_FAMILY_TO_HOST_ADDRESS_TYPE[family];
|
|
249
|
+
if (addressType === undefined) {
|
|
250
|
+
throw new Error(`dns.lookup() Node DNS family \`${family}\` is not supported`);
|
|
251
|
+
}
|
|
252
|
+
addresses.push({
|
|
253
|
+
addressType,
|
|
254
|
+
address,
|
|
255
|
+
hostName: args.hostName,
|
|
256
|
+
service: args.service,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
return addresses;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const HostResolver = NodeDnsLookupHostResolver;
|
|
264
|
+
|
|
265
|
+
exports.HostResolver = HostResolver;
|
|
266
|
+
exports.NodeDnsLookupHostResolver = NodeDnsLookupHostResolver;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aws-sdk/util-dns",
|
|
3
|
-
"version": "3.972.
|
|
3
|
+
"version": "3.972.17",
|
|
4
4
|
"description": "Implementations of DNS host resolvers.",
|
|
5
5
|
"main": "./dist-cjs/index.js",
|
|
6
6
|
"module": "./dist-es/index.js",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"license": "Apache-2.0",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@aws-sdk/types": "^3.973.
|
|
30
|
+
"@aws-sdk/types": "^3.973.14",
|
|
31
31
|
"tslib": "^2.6.2"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
@@ -66,9 +66,6 @@
|
|
|
66
66
|
"react-native": {
|
|
67
67
|
"./dist-es/index": "./dist-es/index.browser",
|
|
68
68
|
"./dist-es/HostResolver": "./dist-es/HostResolver.browser",
|
|
69
|
-
"./dist-es/NodeDnsLookupHostResolver": false
|
|
70
|
-
"./dist-cjs/index": "./dist-cjs/index.browser",
|
|
71
|
-
"./dist-cjs/HostResolver": "./dist-cjs/HostResolver.browser",
|
|
72
|
-
"./dist-cjs/NodeDnsLookupHostResolver": false
|
|
69
|
+
"./dist-es/NodeDnsLookupHostResolver": false
|
|
73
70
|
}
|
|
74
71
|
}
|
package/dist-cjs/HostResolver.js
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
const { HostAddressType } = require("@aws-sdk/types");
|
|
2
|
-
const { ALL, promises: dnsPromises, V4MAPPED } = require("dns");
|
|
3
|
-
const { HostEntryTable } = require("./util/HostEntryTable");
|
|
4
|
-
const NODE_DNS_FAMILY_TO_HOST_ADDRESS_TYPE = {
|
|
5
|
-
4: HostAddressType.A,
|
|
6
|
-
6: HostAddressType.AAAA,
|
|
7
|
-
};
|
|
8
|
-
const DNS_LOOKUP_OPTIONS = {
|
|
9
|
-
all: true,
|
|
10
|
-
hints: V4MAPPED | ALL,
|
|
11
|
-
verbatim: true,
|
|
12
|
-
};
|
|
13
|
-
exports.NodeDnsLookupHostResolver = class NodeDnsLookupHostResolver {
|
|
14
|
-
static DEFAULT_TTL_MS = 30_000;
|
|
15
|
-
static createDefaultCacheProvider = () => new HostEntryTable();
|
|
16
|
-
static DEFAULT_NODE_DNS_LOOKUP = dnsPromises.lookup;
|
|
17
|
-
ttlMs;
|
|
18
|
-
cache;
|
|
19
|
-
nodeDnsLookup;
|
|
20
|
-
constructor({ ttlMs = NodeDnsLookupHostResolver.DEFAULT_TTL_MS, cache = NodeDnsLookupHostResolver.createDefaultCacheProvider(), nodeDnsLookup = NodeDnsLookupHostResolver.DEFAULT_NODE_DNS_LOOKUP, } = {}) {
|
|
21
|
-
this.ttlMs = ttlMs;
|
|
22
|
-
this.cache = cache;
|
|
23
|
-
this.nodeDnsLookup = nodeDnsLookup;
|
|
24
|
-
}
|
|
25
|
-
async resolveAddress(args) {
|
|
26
|
-
const possibleHostEntry = this.cache.get(args.hostName);
|
|
27
|
-
const newNextTimestampToUpdateMs = Date.now() + this.ttlMs;
|
|
28
|
-
if (possibleHostEntry === undefined) {
|
|
29
|
-
const addresses = await this.nodeDnsLookupResolveAddress(args);
|
|
30
|
-
this.cache.set(args, addresses, newNextTimestampToUpdateMs);
|
|
31
|
-
}
|
|
32
|
-
const hostEntry = this.cache.get(args.hostName);
|
|
33
|
-
if (possibleHostEntry !== undefined && Date.now() >= hostEntry.nextTimestampToUpdateMs) {
|
|
34
|
-
try {
|
|
35
|
-
const addresses = await this.nodeDnsLookupResolveAddress(args);
|
|
36
|
-
hostEntry.updateRecords(addresses, newNextTimestampToUpdateMs);
|
|
37
|
-
}
|
|
38
|
-
catch (error) {
|
|
39
|
-
console.error(`Could not update DNS address cache for "${args.hostName}": ${error}`);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
hostEntry.processRecords();
|
|
43
|
-
const result = [];
|
|
44
|
-
if (hostEntry.aRecords.length > 0) {
|
|
45
|
-
result.push(hostEntry.aRecords.cycle());
|
|
46
|
-
}
|
|
47
|
-
if (hostEntry.aaaaRecords.length > 0) {
|
|
48
|
-
result.push(hostEntry.aaaaRecords.cycle());
|
|
49
|
-
}
|
|
50
|
-
if (result.length === 0) {
|
|
51
|
-
throw new Error(`Could not resolve addresses for "${args.hostName}"`);
|
|
52
|
-
}
|
|
53
|
-
return result;
|
|
54
|
-
}
|
|
55
|
-
reportFailureOnAddress(addr) {
|
|
56
|
-
const hostEntry = this.cache.get(addr.hostName);
|
|
57
|
-
if (hostEntry === undefined) {
|
|
58
|
-
throw new Error(`Could not find cached host name "${addr.hostName}"`);
|
|
59
|
-
}
|
|
60
|
-
hostEntry.failAddressInRecords(addr);
|
|
61
|
-
}
|
|
62
|
-
purgeCache(args) {
|
|
63
|
-
if (args?.hostName) {
|
|
64
|
-
this.cache.delete(args.hostName);
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
this.cache.clear();
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
async nodeDnsLookupResolveAddress(args) {
|
|
71
|
-
const addresses = [];
|
|
72
|
-
const ipEntries = await this.nodeDnsLookup(args.hostName, DNS_LOOKUP_OPTIONS);
|
|
73
|
-
for (const { address, family } of ipEntries) {
|
|
74
|
-
const addressType = NODE_DNS_FAMILY_TO_HOST_ADDRESS_TYPE[family];
|
|
75
|
-
if (addressType === undefined) {
|
|
76
|
-
throw new Error(`dns.lookup() Node DNS family \`${family}\` is not supported`);
|
|
77
|
-
}
|
|
78
|
-
addresses.push({
|
|
79
|
-
addressType,
|
|
80
|
-
address,
|
|
81
|
-
hostName: args.hostName,
|
|
82
|
-
service: args.service,
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
return addresses;
|
|
86
|
-
}
|
|
87
|
-
};
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
exports.HostAddressEntryCollection = class HostAddressEntryCollection {
|
|
2
|
-
data = [];
|
|
3
|
-
get length() {
|
|
4
|
-
return this.data.length;
|
|
5
|
-
}
|
|
6
|
-
cycle(collection) {
|
|
7
|
-
if (this.data.length === 0) {
|
|
8
|
-
throw new Error("Cannot cycle an empty collection");
|
|
9
|
-
}
|
|
10
|
-
const entry = this.data.shift();
|
|
11
|
-
(collection || this).append(entry);
|
|
12
|
-
return entry;
|
|
13
|
-
}
|
|
14
|
-
append(entry) {
|
|
15
|
-
this.data.push(entry);
|
|
16
|
-
}
|
|
17
|
-
remove(entry) {
|
|
18
|
-
if (this.length === 0) {
|
|
19
|
-
throw new Error("Cannot remove from an empty collection");
|
|
20
|
-
}
|
|
21
|
-
const index = this.data.findIndex((e) => e.address === entry.address);
|
|
22
|
-
const removedEntry = this.data[index];
|
|
23
|
-
this.data.splice(index, 1);
|
|
24
|
-
return removedEntry;
|
|
25
|
-
}
|
|
26
|
-
[Symbol.iterator]() {
|
|
27
|
-
return this.data[Symbol.iterator]();
|
|
28
|
-
}
|
|
29
|
-
};
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
const { HostAddressType } = require("@aws-sdk/types");
|
|
2
|
-
const { HostAddressEntryCollection } = require("./HostAddressEntryCollection");
|
|
3
|
-
exports.HostEntry = class HostEntry {
|
|
4
|
-
aaaaRecords;
|
|
5
|
-
aRecords;
|
|
6
|
-
failedAaaaRecords;
|
|
7
|
-
failedARecords;
|
|
8
|
-
nextTimestampToUpdateMs;
|
|
9
|
-
constructor(nextTimestampToProcessMs) {
|
|
10
|
-
this.aaaaRecords = new HostAddressEntryCollection();
|
|
11
|
-
this.aRecords = new HostAddressEntryCollection();
|
|
12
|
-
this.failedAaaaRecords = new HostAddressEntryCollection();
|
|
13
|
-
this.failedARecords = new HostAddressEntryCollection();
|
|
14
|
-
this.nextTimestampToUpdateMs = nextTimestampToProcessMs;
|
|
15
|
-
}
|
|
16
|
-
updateRecords(addresses, expirationTtlMs) {
|
|
17
|
-
this.nextTimestampToUpdateMs = expirationTtlMs;
|
|
18
|
-
const addressesToAppend = [];
|
|
19
|
-
for (const freshAddress of addresses) {
|
|
20
|
-
const hostAddressEntry = this.findAddress(freshAddress);
|
|
21
|
-
if (hostAddressEntry !== undefined) {
|
|
22
|
-
hostAddressEntry.expirationTtlMs = expirationTtlMs;
|
|
23
|
-
continue;
|
|
24
|
-
}
|
|
25
|
-
addressesToAppend.push(freshAddress);
|
|
26
|
-
}
|
|
27
|
-
for (const addressToAppend of addressesToAppend) {
|
|
28
|
-
const hostAddressEntry = this.findAddress(addressToAppend);
|
|
29
|
-
if (hostAddressEntry !== undefined) {
|
|
30
|
-
continue;
|
|
31
|
-
}
|
|
32
|
-
const successRecords = this.getGoodRecords(addressToAppend);
|
|
33
|
-
successRecords.append(Object.assign(addressToAppend, {
|
|
34
|
-
expirationTtlMs,
|
|
35
|
-
}));
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
processRecords() {
|
|
39
|
-
this.processRecordsAddressType(this.aRecords, this.failedARecords);
|
|
40
|
-
this.processRecordsAddressType(this.aaaaRecords, this.failedAaaaRecords);
|
|
41
|
-
}
|
|
42
|
-
failAddressInRecords(address) {
|
|
43
|
-
const successRecords = this.getGoodRecords(address);
|
|
44
|
-
const failedRecords = this.getFailedRecords(address);
|
|
45
|
-
const recordsToRemove = [];
|
|
46
|
-
for (const hostAddressEntry of successRecords) {
|
|
47
|
-
if (hostAddressEntry.address === address.address) {
|
|
48
|
-
recordsToRemove.push(hostAddressEntry);
|
|
49
|
-
failedRecords.append(hostAddressEntry);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
for (const recordToRemove of recordsToRemove) {
|
|
53
|
-
successRecords.remove(recordToRemove);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
findAddress(address) {
|
|
57
|
-
const successRecords = this.getGoodRecords(address);
|
|
58
|
-
for (const hostAddressEntry of successRecords) {
|
|
59
|
-
if (address.address === hostAddressEntry.address) {
|
|
60
|
-
return hostAddressEntry;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
const failedRecords = this.getFailedRecords(address);
|
|
64
|
-
for (const hostAddressEntry of failedRecords) {
|
|
65
|
-
if (address.address === hostAddressEntry.address) {
|
|
66
|
-
return hostAddressEntry;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return undefined;
|
|
70
|
-
}
|
|
71
|
-
processRecordsAddressType(successRecords, failedRecords) {
|
|
72
|
-
const successRecordsToRemove = [];
|
|
73
|
-
let successIndex = 0;
|
|
74
|
-
for (const hostAddressEntry of successRecords) {
|
|
75
|
-
if (successIndex === successRecords.length - 1) {
|
|
76
|
-
break;
|
|
77
|
-
}
|
|
78
|
-
if (Date.now() >= hostAddressEntry.expirationTtlMs) {
|
|
79
|
-
successRecordsToRemove.push(hostAddressEntry);
|
|
80
|
-
}
|
|
81
|
-
successIndex++;
|
|
82
|
-
}
|
|
83
|
-
for (const recordToRemove of successRecordsToRemove) {
|
|
84
|
-
successRecords.remove(recordToRemove);
|
|
85
|
-
}
|
|
86
|
-
const failedRecordsToRemove = [];
|
|
87
|
-
let failedIndex = 0;
|
|
88
|
-
for (const hostAddressEntry of failedRecords) {
|
|
89
|
-
if (failedIndex === failedRecords.length - 1) {
|
|
90
|
-
break;
|
|
91
|
-
}
|
|
92
|
-
if (Date.now() >= hostAddressEntry.expirationTtlMs) {
|
|
93
|
-
failedRecordsToRemove.push(hostAddressEntry);
|
|
94
|
-
}
|
|
95
|
-
failedIndex++;
|
|
96
|
-
}
|
|
97
|
-
for (const recordToRemove of failedRecordsToRemove) {
|
|
98
|
-
failedRecords.remove(recordToRemove);
|
|
99
|
-
}
|
|
100
|
-
if (successRecords.length === 0) {
|
|
101
|
-
let hostAddressEntryToPromote = undefined;
|
|
102
|
-
for (const hostAddressEntry of failedRecords) {
|
|
103
|
-
if (Date.now() >= hostAddressEntry.expirationTtlMs) {
|
|
104
|
-
continue;
|
|
105
|
-
}
|
|
106
|
-
hostAddressEntryToPromote = hostAddressEntry;
|
|
107
|
-
break;
|
|
108
|
-
}
|
|
109
|
-
if (hostAddressEntryToPromote !== undefined) {
|
|
110
|
-
failedRecords.remove(hostAddressEntryToPromote);
|
|
111
|
-
successRecords.append(hostAddressEntryToPromote);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
getGoodRecords(address) {
|
|
116
|
-
return address.addressType === HostAddressType.AAAA ? this.aaaaRecords : this.aRecords;
|
|
117
|
-
}
|
|
118
|
-
getFailedRecords(address) {
|
|
119
|
-
return address.addressType === HostAddressType.AAAA ? this.failedAaaaRecords : this.failedARecords;
|
|
120
|
-
}
|
|
121
|
-
};
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
const { HostEntry } = require("./HostEntry");
|
|
2
|
-
exports.HostEntryTable = class HostEntryTable {
|
|
3
|
-
map;
|
|
4
|
-
constructor() {
|
|
5
|
-
this.map = new Map();
|
|
6
|
-
}
|
|
7
|
-
set(args, addresses, nextTimestampToProcessMs) {
|
|
8
|
-
const hostEntry = new HostEntry(nextTimestampToProcessMs);
|
|
9
|
-
hostEntry.updateRecords(addresses, nextTimestampToProcessMs);
|
|
10
|
-
this.map.set(args.hostName, hostEntry);
|
|
11
|
-
}
|
|
12
|
-
get(hostName) {
|
|
13
|
-
return this.map.get(hostName);
|
|
14
|
-
}
|
|
15
|
-
delete(hostName) {
|
|
16
|
-
this.map.delete(hostName);
|
|
17
|
-
}
|
|
18
|
-
clear() {
|
|
19
|
-
this.map.clear();
|
|
20
|
-
}
|
|
21
|
-
get size() {
|
|
22
|
-
return this.map.size;
|
|
23
|
-
}
|
|
24
|
-
};
|