GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
// Copyright Joyent, Inc. and other Node contributors. |
||
2 |
// |
||
3 |
// Permission is hereby granted, free of charge, to any person obtaining a |
||
4 |
// copy of this software and associated documentation files (the |
||
5 |
// "Software"), to deal in the Software without restriction, including |
||
6 |
// without limitation the rights to use, copy, modify, merge, publish, |
||
7 |
// distribute, sublicense, and/or sell copies of the Software, and to permit |
||
8 |
// persons to whom the Software is furnished to do so, subject to the |
||
9 |
// following conditions: |
||
10 |
// |
||
11 |
// The above copyright notice and this permission notice shall be included |
||
12 |
// in all copies or substantial portions of the Software. |
||
13 |
// |
||
14 |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
||
15 |
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||
16 |
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN |
||
17 |
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
||
18 |
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
||
19 |
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
||
20 |
// USE OR OTHER DEALINGS IN THE SOFTWARE. |
||
21 |
|||
22 |
#include "async_wrap-inl.h" |
||
23 |
#include "base_object-inl.h" |
||
24 |
#include "base64-inl.h" |
||
25 |
#include "cares_wrap.h" |
||
26 |
#include "env-inl.h" |
||
27 |
#include "memory_tracker-inl.h" |
||
28 |
#include "node.h" |
||
29 |
#include "node_errors.h" |
||
30 |
#include "req_wrap-inl.h" |
||
31 |
#include "util-inl.h" |
||
32 |
#include "v8.h" |
||
33 |
#include "uv.h" |
||
34 |
|||
35 |
#include <cerrno> |
||
36 |
#include <cstring> |
||
37 |
#include <memory> |
||
38 |
#include <vector> |
||
39 |
#include <unordered_set> |
||
40 |
|||
41 |
#ifndef T_CAA |
||
42 |
# define T_CAA 257 /* Certification Authority Authorization */ |
||
43 |
#endif |
||
44 |
|||
45 |
// OpenBSD does not define these |
||
46 |
#ifndef AI_ALL |
||
47 |
# define AI_ALL 0 |
||
48 |
#endif |
||
49 |
#ifndef AI_V4MAPPED |
||
50 |
# define AI_V4MAPPED 0 |
||
51 |
#endif |
||
52 |
|||
53 |
|||
54 |
namespace node { |
||
55 |
namespace cares_wrap { |
||
56 |
|||
57 |
using v8::Array; |
||
58 |
using v8::Context; |
||
59 |
using v8::EscapableHandleScope; |
||
60 |
using v8::FunctionCallbackInfo; |
||
61 |
using v8::FunctionTemplate; |
||
62 |
using v8::HandleScope; |
||
63 |
using v8::Int32; |
||
64 |
using v8::Integer; |
||
65 |
using v8::Isolate; |
||
66 |
using v8::Just; |
||
67 |
using v8::Local; |
||
68 |
using v8::Maybe; |
||
69 |
using v8::Nothing; |
||
70 |
using v8::Null; |
||
71 |
using v8::Object; |
||
72 |
using v8::String; |
||
73 |
using v8::Value; |
||
74 |
|||
75 |
namespace { |
||
76 |
|||
77 |
Mutex ares_library_mutex; |
||
78 |
|||
79 |
56 |
inline uint16_t cares_get_16bit(const unsigned char* p) { |
|
80 |
56 |
return static_cast<uint32_t>(p[0] << 8U) | (static_cast<uint32_t>(p[1])); |
|
81 |
} |
||
82 |
|||
83 |
18 |
void ares_poll_cb(uv_poll_t* watcher, int status, int events) { |
|
84 |
18 |
NodeAresTask* task = ContainerOf(&NodeAresTask::poll_watcher, watcher); |
|
85 |
18 |
ChannelWrap* channel = task->channel; |
|
86 |
|||
87 |
/* Reset the idle timer */ |
||
88 |
18 |
uv_timer_again(channel->timer_handle()); |
|
89 |
|||
90 |
✗✓ | 18 |
if (status < 0) { |
91 |
/* An error happened. Just pretend that the socket is both readable and */ |
||
92 |
/* writable. */ |
||
93 |
ares_process_fd(channel->cares_channel(), task->sock, task->sock); |
||
94 |
return; |
||
95 |
} |
||
96 |
|||
97 |
/* Process DNS responses */ |
||
98 |
36 |
ares_process_fd(channel->cares_channel(), |
|
99 |
✓✗ | 18 |
events & UV_READABLE ? task->sock : ARES_SOCKET_BAD, |
100 |
✗✓ | 18 |
events & UV_WRITABLE ? task->sock : ARES_SOCKET_BAD); |
101 |
} |
||
102 |
|||
103 |
|||
104 |
30 |
void ares_poll_close_cb(uv_poll_t* watcher) { |
|
105 |
std::unique_ptr<NodeAresTask> free_me( |
||
106 |
30 |
ContainerOf(&NodeAresTask::poll_watcher, watcher)); |
|
107 |
30 |
} |
|
108 |
|||
109 |
|||
110 |
/* Callback from ares when socket operation is started */ |
||
111 |
60 |
void ares_sockstate_cb(void* data, ares_socket_t sock, int read, int write) { |
|
112 |
60 |
ChannelWrap* channel = static_cast<ChannelWrap*>(data); |
|
113 |
NodeAresTask* task; |
||
114 |
|||
115 |
60 |
NodeAresTask lookup_task; |
|
116 |
60 |
lookup_task.sock = sock; |
|
117 |
60 |
auto it = channel->task_list()->find(&lookup_task); |
|
118 |
|||
119 |
✓✓ | 60 |
task = (it == channel->task_list()->end()) ? nullptr : *it; |
120 |
|||
121 |
✓✓✗✓ |
60 |
if (read || write) { |
122 |
✓✗ | 30 |
if (!task) { |
123 |
/* New socket */ |
||
124 |
30 |
channel->StartTimer(); |
|
125 |
|||
126 |
30 |
task = NodeAresTask::Create(channel, sock); |
|
127 |
✗✓ | 30 |
if (task == nullptr) { |
128 |
/* This should never happen unless we're out of memory or something */ |
||
129 |
/* is seriously wrong. The socket won't be polled, but the query will */ |
||
130 |
/* eventually time out. */ |
||
131 |
return; |
||
132 |
} |
||
133 |
|||
134 |
30 |
channel->task_list()->insert(task); |
|
135 |
} |
||
136 |
|||
137 |
/* This should never fail. If it fails anyway, the query will eventually */ |
||
138 |
/* time out. */ |
||
139 |
30 |
uv_poll_start(&task->poll_watcher, |
|
140 |
✓✗✗✓ |
30 |
(read ? UV_READABLE : 0) | (write ? UV_WRITABLE : 0), |
141 |
ares_poll_cb); |
||
142 |
|||
143 |
} else { |
||
144 |
/* read == 0 and write == 0 this is c-ares's way of notifying us that */ |
||
145 |
/* the socket is now closed. We must free the data associated with */ |
||
146 |
/* socket. */ |
||
147 |
✗✓ | 30 |
CHECK(task && |
148 |
"When an ares socket is closed we should have a handle for it"); |
||
149 |
|||
150 |
30 |
channel->task_list()->erase(it); |
|
151 |
30 |
channel->env()->CloseHandle(&task->poll_watcher, ares_poll_close_cb); |
|
152 |
|||
153 |
✓✗ | 30 |
if (channel->task_list()->empty()) { |
154 |
30 |
channel->CloseTimer(); |
|
155 |
} |
||
156 |
} |
||
157 |
} |
||
158 |
|||
159 |
2 |
Local<Array> HostentToNames(Environment* env, struct hostent* host) { |
|
160 |
2 |
EscapableHandleScope scope(env->isolate()); |
|
161 |
|||
162 |
2 |
std::vector<Local<Value>> names; |
|
163 |
|||
164 |
✗✓ | 2 |
for (uint32_t i = 0; host->h_aliases[i] != nullptr; ++i) |
165 |
names.emplace_back(OneByteString(env->isolate(), host->h_aliases[i])); |
||
166 |
|||
167 |
2 |
Local<Array> ret = Array::New(env->isolate(), names.data(), names.size()); |
|
168 |
|||
169 |
2 |
return scope.Escape(ret); |
|
170 |
} |
||
171 |
|||
172 |
4 |
Local<Array> HostentToNames(Environment* env, |
|
173 |
struct hostent* host, |
||
174 |
Local<Array> names) { |
||
175 |
4 |
size_t offset = names->Length(); |
|
176 |
|||
177 |
✓✓ | 8 |
for (uint32_t i = 0; host->h_aliases[i] != nullptr; ++i) { |
178 |
8 |
names->Set( |
|
179 |
env->context(), |
||
180 |
i + offset, |
||
181 |
12 |
OneByteString(env->isolate(), host->h_aliases[i])).Check(); |
|
182 |
} |
||
183 |
|||
184 |
4 |
return names; |
|
185 |
} |
||
186 |
|||
187 |
template <typename T> |
||
188 |
18 |
Local<Array> AddrTTLToArray( |
|
189 |
Environment* env, |
||
190 |
const T* addrttls, |
||
191 |
size_t naddrttls) { |
||
192 |
36 |
MaybeStackBuffer<Local<Value>, 8> ttls(naddrttls); |
|
193 |
✓✓ | 36 |
for (size_t i = 0; i < naddrttls; i++) |
194 |
36 |
ttls[i] = Integer::NewFromUnsigned(env->isolate(), addrttls[i].ttl); |
|
195 |
|||
196 |
18 |
return Array::New(env->isolate(), ttls.out(), naddrttls); |
|
197 |
} |
||
198 |
|||
199 |
27 |
int ParseGeneralReply( |
|
200 |
Environment* env, |
||
201 |
const unsigned char* buf, |
||
202 |
int len, |
||
203 |
int* type, |
||
204 |
Local<Array> ret, |
||
205 |
void* addrttls = nullptr, |
||
206 |
int* naddrttls = nullptr) { |
||
207 |
54 |
HandleScope handle_scope(env->isolate()); |
|
208 |
hostent* host; |
||
209 |
|||
210 |
int status; |
||
211 |
✓✓✓✓ ✗ |
27 |
switch (*type) { |
212 |
13 |
case ns_t_a: |
|
213 |
case ns_t_cname: |
||
214 |
case ns_t_cname_or_a: |
||
215 |
13 |
status = ares_parse_a_reply(buf, |
|
216 |
len, |
||
217 |
&host, |
||
218 |
static_cast<ares_addrttl*>(addrttls), |
||
219 |
naddrttls); |
||
220 |
13 |
break; |
|
221 |
6 |
case ns_t_aaaa: |
|
222 |
6 |
status = ares_parse_aaaa_reply(buf, |
|
223 |
len, |
||
224 |
&host, |
||
225 |
static_cast<ares_addr6ttl*>(addrttls), |
||
226 |
naddrttls); |
||
227 |
6 |
break; |
|
228 |
4 |
case ns_t_ns: |
|
229 |
4 |
status = ares_parse_ns_reply(buf, len, &host); |
|
230 |
4 |
break; |
|
231 |
4 |
case ns_t_ptr: |
|
232 |
4 |
status = ares_parse_ptr_reply(buf, len, nullptr, 0, AF_INET, &host); |
|
233 |
4 |
break; |
|
234 |
default: |
||
235 |
CHECK(0 && "Bad NS type"); |
||
236 |
break; |
||
237 |
} |
||
238 |
|||
239 |
✓✓ | 27 |
if (status != ARES_SUCCESS) |
240 |
2 |
return status; |
|
241 |
|||
242 |
✗✓ | 25 |
CHECK_NOT_NULL(host); |
243 |
50 |
HostEntPointer ptr(host); |
|
244 |
|||
245 |
/* If it's `CNAME`, return the CNAME value; |
||
246 |
* And if it's `CNAME_OR_A` and it has value in `h_name` and `h_aliases[0]`, |
||
247 |
* we consider it's a CNAME record, otherwise we consider it's an A record. */ |
||
248 |
✓✓✓✗ ✓✗✗✓ |
50 |
if ((*type == ns_t_cname_or_a && ptr->h_name && ptr->h_aliases[0]) || |
249 |
✗✓ | 25 |
*type == ns_t_cname) { |
250 |
// A cname lookup always returns a single record but we follow the |
||
251 |
// common API here. |
||
252 |
*type = ns_t_cname; |
||
253 |
ret->Set(env->context(), |
||
254 |
ret->Length(), |
||
255 |
OneByteString(env->isolate(), ptr->h_name)).Check(); |
||
256 |
return ARES_SUCCESS; |
||
257 |
} |
||
258 |
|||
259 |
✓✓ | 25 |
if (*type == ns_t_cname_or_a) |
260 |
4 |
*type = ns_t_a; |
|
261 |
|||
262 |
✓✓ | 25 |
if (*type == ns_t_ns) { |
263 |
4 |
HostentToNames(env, ptr.get(), ret); |
|
264 |
✓✓ | 21 |
} else if (*type == ns_t_ptr) { |
265 |
4 |
uint32_t offset = ret->Length(); |
|
266 |
✓✓ | 8 |
for (uint32_t i = 0; ptr->h_aliases[i] != nullptr; i++) { |
267 |
4 |
auto alias = OneByteString(env->isolate(), ptr->h_aliases[i]); |
|
268 |
8 |
ret->Set(env->context(), i + offset, alias).Check(); |
|
269 |
} |
||
270 |
} else { |
||
271 |
17 |
uint32_t offset = ret->Length(); |
|
272 |
char ip[INET6_ADDRSTRLEN]; |
||
273 |
✓✓ | 34 |
for (uint32_t i = 0; ptr->h_addr_list[i] != nullptr; ++i) { |
274 |
17 |
uv_inet_ntop(ptr->h_addrtype, ptr->h_addr_list[i], ip, sizeof(ip)); |
|
275 |
17 |
auto address = OneByteString(env->isolate(), ip); |
|
276 |
34 |
ret->Set(env->context(), i + offset, address).Check(); |
|
277 |
} |
||
278 |
} |
||
279 |
|||
280 |
25 |
return ARES_SUCCESS; |
|
281 |
} |
||
282 |
|||
283 |
4 |
int ParseMxReply( |
|
284 |
Environment* env, |
||
285 |
const unsigned char* buf, |
||
286 |
int len, |
||
287 |
Local<Array> ret, |
||
288 |
bool need_type = false) { |
||
289 |
8 |
HandleScope handle_scope(env->isolate()); |
|
290 |
|||
291 |
struct ares_mx_reply* mx_start; |
||
292 |
4 |
int status = ares_parse_mx_reply(buf, len, &mx_start); |
|
293 |
✗✓ | 4 |
if (status != ARES_SUCCESS) |
294 |
return status; |
||
295 |
|||
296 |
4 |
uint32_t offset = ret->Length(); |
|
297 |
4 |
ares_mx_reply* current = mx_start; |
|
298 |
✓✓ | 8 |
for (uint32_t i = 0; current != nullptr; ++i, current = current->next) { |
299 |
4 |
Local<Object> mx_record = Object::New(env->isolate()); |
|
300 |
4 |
mx_record->Set(env->context(), |
|
301 |
env->exchange_string(), |
||
302 |
16 |
OneByteString(env->isolate(), current->host)).Check(); |
|
303 |
4 |
mx_record->Set(env->context(), |
|
304 |
env->priority_string(), |
||
305 |
12 |
Integer::New(env->isolate(), current->priority)).Check(); |
|
306 |
✓✗ | 4 |
if (need_type) |
307 |
4 |
mx_record->Set(env->context(), |
|
308 |
env->type_string(), |
||
309 |
16 |
env->dns_mx_string()).Check(); |
|
310 |
|||
311 |
8 |
ret->Set(env->context(), i + offset, mx_record).Check(); |
|
312 |
} |
||
313 |
|||
314 |
4 |
ares_free_data(mx_start); |
|
315 |
4 |
return ARES_SUCCESS; |
|
316 |
} |
||
317 |
|||
318 |
4 |
int ParseCaaReply( |
|
319 |
Environment* env, |
||
320 |
const unsigned char* buf, |
||
321 |
int len, |
||
322 |
Local<Array> ret, |
||
323 |
bool need_type = false) { |
||
324 |
8 |
HandleScope handle_scope(env->isolate()); |
|
325 |
|||
326 |
struct ares_caa_reply* caa_start; |
||
327 |
4 |
int status = ares_parse_caa_reply(buf, len, &caa_start); |
|
328 |
✗✓ | 4 |
if (status != ARES_SUCCESS) |
329 |
return status; |
||
330 |
|||
331 |
4 |
uint32_t offset = ret->Length(); |
|
332 |
4 |
ares_caa_reply* current = caa_start; |
|
333 |
✓✓ | 6 |
for (uint32_t i = 0; current != nullptr; ++i, current = current->next) { |
334 |
2 |
Local<Object> caa_record = Object::New(env->isolate()); |
|
335 |
|||
336 |
2 |
caa_record->Set(env->context(), |
|
337 |
env->dns_critical_string(), |
||
338 |
8 |
Integer::New(env->isolate(), current->critical)).Check(); |
|
339 |
2 |
caa_record->Set(env->context(), |
|
340 |
2 |
OneByteString(env->isolate(), current->property), |
|
341 |
6 |
OneByteString(env->isolate(), current->value)).Check(); |
|
342 |
✓✗ | 2 |
if (need_type) |
343 |
2 |
caa_record->Set(env->context(), |
|
344 |
env->type_string(), |
||
345 |
8 |
env->dns_caa_string()).Check(); |
|
346 |
|||
347 |
4 |
ret->Set(env->context(), i + offset, caa_record).Check(); |
|
348 |
} |
||
349 |
|||
350 |
4 |
ares_free_data(caa_start); |
|
351 |
4 |
return ARES_SUCCESS; |
|
352 |
} |
||
353 |
|||
354 |
4 |
int ParseTxtReply( |
|
355 |
Environment* env, |
||
356 |
const unsigned char* buf, |
||
357 |
int len, |
||
358 |
Local<Array> ret, |
||
359 |
bool need_type = false) { |
||
360 |
8 |
HandleScope handle_scope(env->isolate()); |
|
361 |
|||
362 |
struct ares_txt_ext* txt_out; |
||
363 |
|||
364 |
4 |
int status = ares_parse_txt_reply_ext(buf, len, &txt_out); |
|
365 |
✗✓ | 4 |
if (status != ARES_SUCCESS) |
366 |
return status; |
||
367 |
|||
368 |
Local<Array> txt_chunk; |
||
369 |
|||
370 |
4 |
struct ares_txt_ext* current = txt_out; |
|
371 |
4 |
uint32_t i = 0, j; |
|
372 |
4 |
uint32_t offset = ret->Length(); |
|
373 |
✓✓ | 8 |
for (j = 0; current != nullptr; current = current->next) { |
374 |
Local<String> txt = |
||
375 |
4 |
OneByteString(env->isolate(), current->txt, current->length); |
|
376 |
|||
377 |
// New record found - write out the current chunk |
||
378 |
✓✓ | 4 |
if (current->record_start) { |
379 |
✗✓ | 2 |
if (!txt_chunk.IsEmpty()) { |
380 |
if (need_type) { |
||
381 |
Local<Object> elem = Object::New(env->isolate()); |
||
382 |
elem->Set(env->context(), env->entries_string(), txt_chunk).Check(); |
||
383 |
elem->Set(env->context(), |
||
384 |
env->type_string(), |
||
385 |
env->dns_txt_string()).Check(); |
||
386 |
ret->Set(env->context(), offset + i++, elem).Check(); |
||
387 |
} else { |
||
388 |
ret->Set(env->context(), offset + i++, txt_chunk).Check(); |
||
389 |
} |
||
390 |
} |
||
391 |
|||
392 |
2 |
txt_chunk = Array::New(env->isolate()); |
|
393 |
2 |
j = 0; |
|
394 |
} |
||
395 |
|||
396 |
8 |
txt_chunk->Set(env->context(), j++, txt).Check(); |
|
397 |
} |
||
398 |
|||
399 |
// Push last chunk if it isn't empty |
||
400 |
✓✓ | 4 |
if (!txt_chunk.IsEmpty()) { |
401 |
✓✗ | 2 |
if (need_type) { |
402 |
2 |
Local<Object> elem = Object::New(env->isolate()); |
|
403 |
6 |
elem->Set(env->context(), env->entries_string(), txt_chunk).Check(); |
|
404 |
2 |
elem->Set(env->context(), |
|
405 |
env->type_string(), |
||
406 |
8 |
env->dns_txt_string()).Check(); |
|
407 |
4 |
ret->Set(env->context(), offset + i, elem).Check(); |
|
408 |
} else { |
||
409 |
ret->Set(env->context(), offset + i, txt_chunk).Check(); |
||
410 |
} |
||
411 |
} |
||
412 |
|||
413 |
4 |
ares_free_data(txt_out); |
|
414 |
4 |
return ARES_SUCCESS; |
|
415 |
} |
||
416 |
|||
417 |
|||
418 |
4 |
int ParseSrvReply( |
|
419 |
Environment* env, |
||
420 |
const unsigned char* buf, |
||
421 |
int len, |
||
422 |
Local<Array> ret, |
||
423 |
bool need_type = false) { |
||
424 |
8 |
HandleScope handle_scope(env->isolate()); |
|
425 |
|||
426 |
struct ares_srv_reply* srv_start; |
||
427 |
4 |
int status = ares_parse_srv_reply(buf, len, &srv_start); |
|
428 |
✗✓ | 4 |
if (status != ARES_SUCCESS) |
429 |
return status; |
||
430 |
|||
431 |
4 |
ares_srv_reply* current = srv_start; |
|
432 |
4 |
int offset = ret->Length(); |
|
433 |
✗✓ | 4 |
for (uint32_t i = 0; current != nullptr; ++i, current = current->next) { |
434 |
Local<Object> srv_record = Object::New(env->isolate()); |
||
435 |
srv_record->Set(env->context(), |
||
436 |
env->name_string(), |
||
437 |
OneByteString(env->isolate(), current->host)).Check(); |
||
438 |
srv_record->Set(env->context(), |
||
439 |
env->port_string(), |
||
440 |
Integer::New(env->isolate(), current->port)).Check(); |
||
441 |
srv_record->Set(env->context(), |
||
442 |
env->priority_string(), |
||
443 |
Integer::New(env->isolate(), current->priority)).Check(); |
||
444 |
srv_record->Set(env->context(), |
||
445 |
env->weight_string(), |
||
446 |
Integer::New(env->isolate(), current->weight)).Check(); |
||
447 |
if (need_type) |
||
448 |
srv_record->Set(env->context(), |
||
449 |
env->type_string(), |
||
450 |
env->dns_srv_string()).Check(); |
||
451 |
|||
452 |
ret->Set(env->context(), i + offset, srv_record).Check(); |
||
453 |
} |
||
454 |
|||
455 |
4 |
ares_free_data(srv_start); |
|
456 |
4 |
return ARES_SUCCESS; |
|
457 |
} |
||
458 |
|||
459 |
|||
460 |
4 |
int ParseNaptrReply( |
|
461 |
Environment* env, |
||
462 |
const unsigned char* buf, |
||
463 |
int len, |
||
464 |
Local<Array> ret, |
||
465 |
bool need_type = false) { |
||
466 |
8 |
HandleScope handle_scope(env->isolate()); |
|
467 |
|||
468 |
ares_naptr_reply* naptr_start; |
||
469 |
4 |
int status = ares_parse_naptr_reply(buf, len, &naptr_start); |
|
470 |
|||
471 |
✗✓ | 4 |
if (status != ARES_SUCCESS) |
472 |
return status; |
||
473 |
|||
474 |
4 |
ares_naptr_reply* current = naptr_start; |
|
475 |
4 |
int offset = ret->Length(); |
|
476 |
✗✓ | 4 |
for (uint32_t i = 0; current != nullptr; ++i, current = current->next) { |
477 |
Local<Object> naptr_record = Object::New(env->isolate()); |
||
478 |
naptr_record->Set(env->context(), |
||
479 |
env->flags_string(), |
||
480 |
OneByteString(env->isolate(), current->flags)).Check(); |
||
481 |
naptr_record->Set(env->context(), |
||
482 |
env->service_string(), |
||
483 |
OneByteString(env->isolate(), |
||
484 |
current->service)).Check(); |
||
485 |
naptr_record->Set(env->context(), |
||
486 |
env->regexp_string(), |
||
487 |
OneByteString(env->isolate(), |
||
488 |
current->regexp)).Check(); |
||
489 |
naptr_record->Set(env->context(), |
||
490 |
env->replacement_string(), |
||
491 |
OneByteString(env->isolate(), |
||
492 |
current->replacement)).Check(); |
||
493 |
naptr_record->Set(env->context(), |
||
494 |
env->order_string(), |
||
495 |
Integer::New(env->isolate(), current->order)).Check(); |
||
496 |
naptr_record->Set(env->context(), |
||
497 |
env->preference_string(), |
||
498 |
Integer::New(env->isolate(), |
||
499 |
current->preference)).Check(); |
||
500 |
if (need_type) |
||
501 |
naptr_record->Set(env->context(), |
||
502 |
env->type_string(), |
||
503 |
env->dns_naptr_string()).Check(); |
||
504 |
|||
505 |
ret->Set(env->context(), i + offset, naptr_record).Check(); |
||
506 |
} |
||
507 |
|||
508 |
4 |
ares_free_data(naptr_start); |
|
509 |
4 |
return ARES_SUCCESS; |
|
510 |
} |
||
511 |
|||
512 |
|||
513 |
4 |
int ParseSoaReply( |
|
514 |
Environment* env, |
||
515 |
unsigned char* buf, |
||
516 |
int len, |
||
517 |
Local<Object>* ret) { |
||
518 |
4 |
EscapableHandleScope handle_scope(env->isolate()); |
|
519 |
|||
520 |
// Manage memory using standardard smart pointer std::unique_tr |
||
521 |
struct AresDeleter { |
||
522 |
38 |
void operator()(char* ptr) const noexcept { ares_free_string(ptr); } |
|
523 |
}; |
||
524 |
using ares_unique_ptr = std::unique_ptr<char[], AresDeleter>; |
||
525 |
|||
526 |
// Can't use ares_parse_soa_reply() here which can only parse single record |
||
527 |
4 |
const unsigned int ancount = cares_get_16bit(buf + 6); |
|
528 |
4 |
unsigned char* ptr = buf + NS_HFIXEDSZ; |
|
529 |
4 |
char* name_temp = nullptr; |
|
530 |
long temp_len; // NOLINT(runtime/int) |
||
531 |
4 |
int status = ares_expand_name(ptr, buf, len, &name_temp, &temp_len); |
|
532 |
✗✓ | 4 |
if (status != ARES_SUCCESS) { |
533 |
// returns EBADRESP in case of invalid input |
||
534 |
return status == ARES_EBADNAME ? ARES_EBADRESP : status; |
||
535 |
} |
||
536 |
|||
537 |
8 |
const ares_unique_ptr name(name_temp); |
|
538 |
|||
539 |
✗✓ | 4 |
if (ptr + temp_len + NS_QFIXEDSZ > buf + len) { |
540 |
return ARES_EBADRESP; |
||
541 |
} |
||
542 |
4 |
ptr += temp_len + NS_QFIXEDSZ; |
|
543 |
|||
544 |
✓✗ | 26 |
for (unsigned int i = 0; i < ancount; i++) { |
545 |
26 |
char* rr_name_temp = nullptr; |
|
546 |
long rr_temp_len; // NOLINT(runtime/int) |
||
547 |
26 |
int status2 = ares_expand_name(ptr, buf, len, &rr_name_temp, &rr_temp_len); |
|
548 |
|||
549 |
✗✓ | 26 |
if (status2 != ARES_SUCCESS) |
550 |
return status2 == ARES_EBADNAME ? ARES_EBADRESP : status2; |
||
551 |
|||
552 |
26 |
const ares_unique_ptr rr_name(rr_name_temp); |
|
553 |
|||
554 |
26 |
ptr += rr_temp_len; |
|
555 |
✗✓ | 26 |
if (ptr + NS_RRFIXEDSZ > buf + len) { |
556 |
return ARES_EBADRESP; |
||
557 |
} |
||
558 |
|||
559 |
26 |
const int rr_type = cares_get_16bit(ptr); |
|
560 |
26 |
const int rr_len = cares_get_16bit(ptr + 8); |
|
561 |
26 |
ptr += NS_RRFIXEDSZ; |
|
562 |
|||
563 |
// only need SOA |
||
564 |
✓✓ | 26 |
if (rr_type == ns_t_soa) { |
565 |
4 |
char* nsname_temp = nullptr; |
|
566 |
long nsname_temp_len; // NOLINT(runtime/int) |
||
567 |
|||
568 |
4 |
int status3 = ares_expand_name(ptr, buf, len, |
|
569 |
&nsname_temp, |
||
570 |
&nsname_temp_len); |
||
571 |
✗✓ | 4 |
if (status3 != ARES_SUCCESS) { |
572 |
return status3 == ARES_EBADNAME ? ARES_EBADRESP : status3; |
||
573 |
} |
||
574 |
4 |
const ares_unique_ptr nsname(nsname_temp); |
|
575 |
4 |
ptr += nsname_temp_len; |
|
576 |
|||
577 |
4 |
char* hostmaster_temp = nullptr; |
|
578 |
long hostmaster_temp_len; // NOLINT(runtime/int) |
||
579 |
4 |
int status4 = ares_expand_name(ptr, buf, len, |
|
580 |
&hostmaster_temp, |
||
581 |
&hostmaster_temp_len); |
||
582 |
✗✓ | 4 |
if (status4 != ARES_SUCCESS) { |
583 |
return status4 == ARES_EBADNAME ? ARES_EBADRESP : status4; |
||
584 |
} |
||
585 |
4 |
const ares_unique_ptr hostmaster(hostmaster_temp); |
|
586 |
4 |
ptr += hostmaster_temp_len; |
|
587 |
|||
588 |
✗✓ | 4 |
if (ptr + 5 * 4 > buf + len) { |
589 |
return ARES_EBADRESP; |
||
590 |
} |
||
591 |
|||
592 |
4 |
const unsigned int serial = ReadUint32BE(ptr + 0 * 4); |
|
593 |
4 |
const unsigned int refresh = ReadUint32BE(ptr + 1 * 4); |
|
594 |
4 |
const unsigned int retry = ReadUint32BE(ptr + 2 * 4); |
|
595 |
4 |
const unsigned int expire = ReadUint32BE(ptr + 3 * 4); |
|
596 |
4 |
const unsigned int minttl = ReadUint32BE(ptr + 4 * 4); |
|
597 |
|||
598 |
4 |
Local<Object> soa_record = Object::New(env->isolate()); |
|
599 |
4 |
soa_record->Set(env->context(), |
|
600 |
env->nsname_string(), |
||
601 |
16 |
OneByteString(env->isolate(), nsname.get())).Check(); |
|
602 |
4 |
soa_record->Set(env->context(), |
|
603 |
env->hostmaster_string(), |
||
604 |
OneByteString(env->isolate(), |
||
605 |
16 |
hostmaster.get())).Check(); |
|
606 |
4 |
soa_record->Set(env->context(), |
|
607 |
env->serial_string(), |
||
608 |
16 |
Integer::NewFromUnsigned(env->isolate(), serial)).Check(); |
|
609 |
4 |
soa_record->Set(env->context(), |
|
610 |
env->refresh_string(), |
||
611 |
16 |
Integer::New(env->isolate(), refresh)).Check(); |
|
612 |
4 |
soa_record->Set(env->context(), |
|
613 |
env->retry_string(), |
||
614 |
16 |
Integer::New(env->isolate(), retry)).Check(); |
|
615 |
4 |
soa_record->Set(env->context(), |
|
616 |
env->expire_string(), |
||
617 |
16 |
Integer::New(env->isolate(), expire)).Check(); |
|
618 |
4 |
soa_record->Set(env->context(), |
|
619 |
env->minttl_string(), |
||
620 |
16 |
Integer::NewFromUnsigned(env->isolate(), minttl)).Check(); |
|
621 |
4 |
soa_record->Set(env->context(), |
|
622 |
env->type_string(), |
||
623 |
16 |
env->dns_soa_string()).Check(); |
|
624 |
|||
625 |
|||
626 |
4 |
*ret = handle_scope.Escape(soa_record); |
|
627 |
4 |
break; |
|
628 |
} |
||
629 |
|||
630 |
22 |
ptr += rr_len; |
|
631 |
} |
||
632 |
|||
633 |
4 |
return ARES_SUCCESS; |
|
634 |
} |
||
635 |
} // anonymous namespace |
||
636 |
|||
637 |
1191 |
ChannelWrap::ChannelWrap( |
|
638 |
Environment* env, |
||
639 |
Local<Object> object, |
||
640 |
int timeout, |
||
641 |
1191 |
int tries) |
|
642 |
: AsyncWrap(env, object, PROVIDER_DNSCHANNEL), |
||
643 |
timeout_(timeout), |
||
644 |
1191 |
tries_(tries) { |
|
645 |
1191 |
MakeWeak(); |
|
646 |
|||
647 |
1191 |
Setup(); |
|
648 |
1191 |
} |
|
649 |
|||
650 |
4 |
void ChannelWrap::MemoryInfo(MemoryTracker* tracker) const { |
|
651 |
✗✓ | 4 |
if (timer_handle_ != nullptr) |
652 |
tracker->TrackField("timer_handle", *timer_handle_); |
||
653 |
4 |
tracker->TrackField("task_list", task_list_, "NodeAresTask::List"); |
|
654 |
4 |
} |
|
655 |
|||
656 |
1191 |
void ChannelWrap::New(const FunctionCallbackInfo<Value>& args) { |
|
657 |
✗✓ | 1191 |
CHECK(args.IsConstructCall()); |
658 |
✗✓ | 1191 |
CHECK_EQ(args.Length(), 2); |
659 |
✗✓ | 1191 |
CHECK(args[0]->IsInt32()); |
660 |
✗✓ | 1191 |
CHECK(args[1]->IsInt32()); |
661 |
✓✗ | 2382 |
const int timeout = args[0].As<Int32>()->Value(); |
662 |
2382 |
const int tries = args[1].As<Int32>()->Value(); |
|
663 |
1191 |
Environment* env = Environment::GetCurrent(args); |
|
664 |
1191 |
new ChannelWrap(env, args.This(), timeout, tries); |
|
665 |
1191 |
} |
|
666 |
|||
667 |
5294 |
GetAddrInfoReqWrap::GetAddrInfoReqWrap( |
|
668 |
Environment* env, |
||
669 |
Local<Object> req_wrap_obj, |
||
670 |
5294 |
bool verbatim) |
|
671 |
: ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETADDRINFOREQWRAP), |
||
672 |
5294 |
verbatim_(verbatim) {} |
|
673 |
|||
674 |
6 |
GetNameInfoReqWrap::GetNameInfoReqWrap( |
|
675 |
Environment* env, |
||
676 |
6 |
Local<Object> req_wrap_obj) |
|
677 |
6 |
: ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETNAMEINFOREQWRAP) {} |
|
678 |
|||
679 |
/* This is called once per second by loop->timer. It is used to constantly */ |
||
680 |
/* call back into c-ares for possibly processing timeouts. */ |
||
681 |
76 |
void ChannelWrap::AresTimeout(uv_timer_t* handle) { |
|
682 |
76 |
ChannelWrap* channel = static_cast<ChannelWrap*>(handle->data); |
|
683 |
✗✓ | 76 |
CHECK_EQ(channel->timer_handle(), handle); |
684 |
✗✓ | 76 |
CHECK_EQ(false, channel->task_list()->empty()); |
685 |
76 |
ares_process_fd(channel->cares_channel(), ARES_SOCKET_BAD, ARES_SOCKET_BAD); |
|
686 |
76 |
} |
|
687 |
|||
688 |
|||
689 |
void NodeAresTask::MemoryInfo(MemoryTracker* tracker) const { |
||
690 |
tracker->TrackField("channel", channel); |
||
691 |
} |
||
692 |
|||
693 |
/* Allocates and returns a new NodeAresTask */ |
||
694 |
30 |
NodeAresTask* NodeAresTask::Create(ChannelWrap* channel, ares_socket_t sock) { |
|
695 |
30 |
auto task = new NodeAresTask(); |
|
696 |
|||
697 |
30 |
task->channel = channel; |
|
698 |
30 |
task->sock = sock; |
|
699 |
|||
700 |
30 |
if (uv_poll_init_socket(channel->env()->event_loop(), |
|
701 |
✗✓ | 30 |
&task->poll_watcher, sock) < 0) { |
702 |
/* This should never happen. */ |
||
703 |
delete task; |
||
704 |
return nullptr; |
||
705 |
} |
||
706 |
|||
707 |
30 |
return task; |
|
708 |
} |
||
709 |
|||
710 |
1191 |
void ChannelWrap::Setup() { |
|
711 |
struct ares_options options; |
||
712 |
1191 |
memset(&options, 0, sizeof(options)); |
|
713 |
1191 |
options.flags = ARES_FLAG_NOCHECKRESP; |
|
714 |
1191 |
options.sock_state_cb = ares_sockstate_cb; |
|
715 |
1191 |
options.sock_state_cb_data = this; |
|
716 |
1191 |
options.timeout = timeout_; |
|
717 |
1191 |
options.tries = tries_; |
|
718 |
|||
719 |
int r; |
||
720 |
✓✗ | 1191 |
if (!library_inited_) { |
721 |
1191 |
Mutex::ScopedLock lock(ares_library_mutex); |
|
722 |
// Multiple calls to ares_library_init() increase a reference counter, |
||
723 |
// so this is a no-op except for the first call to it. |
||
724 |
1191 |
r = ares_library_init(ARES_LIB_INIT_ALL); |
|
725 |
✗✓ | 1191 |
if (r != ARES_SUCCESS) |
726 |
return env()->ThrowError(ToErrorCodeString(r)); |
||
727 |
} |
||
728 |
|||
729 |
/* We do the call to ares_init_option for caller. */ |
||
730 |
1191 |
const int optmask = |
|
731 |
ARES_OPT_FLAGS | ARES_OPT_TIMEOUTMS | |
||
732 |
ARES_OPT_SOCK_STATE_CB | ARES_OPT_TRIES; |
||
733 |
1191 |
r = ares_init_options(&channel_, &options, optmask); |
|
734 |
|||
735 |
✗✓ | 1191 |
if (r != ARES_SUCCESS) { |
736 |
Mutex::ScopedLock lock(ares_library_mutex); |
||
737 |
ares_library_cleanup(); |
||
738 |
return env()->ThrowError(ToErrorCodeString(r)); |
||
739 |
} |
||
740 |
|||
741 |
1191 |
library_inited_ = true; |
|
742 |
} |
||
743 |
|||
744 |
30 |
void ChannelWrap::StartTimer() { |
|
745 |
✓✗ | 30 |
if (timer_handle_ == nullptr) { |
746 |
30 |
timer_handle_ = new uv_timer_t(); |
|
747 |
30 |
timer_handle_->data = static_cast<void*>(this); |
|
748 |
30 |
uv_timer_init(env()->event_loop(), timer_handle_); |
|
749 |
} else if (uv_is_active(reinterpret_cast<uv_handle_t*>(timer_handle_))) { |
||
750 |
return; |
||
751 |
} |
||
752 |
30 |
int timeout = timeout_; |
|
753 |
✓✓ | 30 |
if (timeout == 0) timeout = 1; |
754 |
✓✓✗✓ |
30 |
if (timeout < 0 || timeout > 1000) timeout = 1000; |
755 |
30 |
uv_timer_start(timer_handle_, AresTimeout, timeout, timeout); |
|
756 |
} |
||
757 |
|||
758 |
1183 |
void ChannelWrap::CloseTimer() { |
|
759 |
✓✓ | 1183 |
if (timer_handle_ == nullptr) |
760 |
1153 |
return; |
|
761 |
|||
762 |
60 |
env()->CloseHandle(timer_handle_, [](uv_timer_t* handle) { delete handle; }); |
|
763 |
30 |
timer_handle_ = nullptr; |
|
764 |
} |
||
765 |
|||
766 |
4612 |
ChannelWrap::~ChannelWrap() { |
|
767 |
2306 |
ares_destroy(channel_); |
|
768 |
|||
769 |
✓✗ | 2306 |
if (library_inited_) { |
770 |
4612 |
Mutex::ScopedLock lock(ares_library_mutex); |
|
771 |
// This decreases the reference counter increased by ares_library_init(). |
||
772 |
2306 |
ares_library_cleanup(); |
|
773 |
} |
||
774 |
|||
775 |
2306 |
CloseTimer(); |
|
776 |
4612 |
} |
|
777 |
|||
778 |
|||
779 |
105 |
void ChannelWrap::ModifyActivityQueryCount(int count) { |
|
780 |
105 |
active_query_count_ += count; |
|
781 |
✗✓ | 105 |
CHECK_GE(active_query_count_, 0); |
782 |
105 |
} |
|
783 |
|||
784 |
|||
785 |
/** |
||
786 |
* This function is to check whether current servers are fallback servers |
||
787 |
* when cares initialized. |
||
788 |
* |
||
789 |
* The fallback servers of cares is [ "127.0.0.1" ] with no user additional |
||
790 |
* setting. |
||
791 |
*/ |
||
792 |
50 |
void ChannelWrap::EnsureServers() { |
|
793 |
/* if last query is OK or servers are set by user self, do not check */ |
||
794 |
✗✓✗✗ |
50 |
if (query_last_ok_ || !is_servers_default_) { |
795 |
50 |
return; |
|
796 |
} |
||
797 |
|||
798 |
ares_addr_port_node* servers = nullptr; |
||
799 |
|||
800 |
ares_get_servers_ports(channel_, &servers); |
||
801 |
|||
802 |
/* if no server or multi-servers, ignore */ |
||
803 |
if (servers == nullptr) return; |
||
804 |
if (servers->next != nullptr) { |
||
805 |
ares_free_data(servers); |
||
806 |
is_servers_default_ = false; |
||
807 |
return; |
||
808 |
} |
||
809 |
|||
810 |
/* if the only server is not 127.0.0.1, ignore */ |
||
811 |
if (servers[0].family != AF_INET || |
||
812 |
servers[0].addr.addr4.s_addr != htonl(INADDR_LOOPBACK) || |
||
813 |
servers[0].tcp_port != 0 || |
||
814 |
servers[0].udp_port != 0) { |
||
815 |
ares_free_data(servers); |
||
816 |
is_servers_default_ = false; |
||
817 |
return; |
||
818 |
} |
||
819 |
|||
820 |
ares_free_data(servers); |
||
821 |
servers = nullptr; |
||
822 |
|||
823 |
/* destroy channel and reset channel */ |
||
824 |
ares_destroy(channel_); |
||
825 |
|||
826 |
CloseTimer(); |
||
827 |
Setup(); |
||
828 |
} |
||
829 |
|||
830 |
8 |
int AnyTraits::Send(QueryWrap<AnyTraits>* wrap, const char* name) { |
|
831 |
8 |
wrap->AresQuery(name, ns_c_in, ns_t_any); |
|
832 |
8 |
return 0; |
|
833 |
} |
||
834 |
|||
835 |
36 |
int ATraits::Send(QueryWrap<ATraits>* wrap, const char* name) { |
|
836 |
36 |
wrap->AresQuery(name, ns_c_in, ns_t_a); |
|
837 |
36 |
return 0; |
|
838 |
} |
||
839 |
|||
840 |
3 |
int AaaaTraits::Send(QueryWrap<AaaaTraits>* wrap, const char* name) { |
|
841 |
3 |
wrap->AresQuery(name, ns_c_in, ns_t_aaaa); |
|
842 |
3 |
return 0; |
|
843 |
} |
||
844 |
|||
845 |
int CaaTraits::Send(QueryWrap<CaaTraits>* wrap, const char* name) { |
||
846 |
wrap->AresQuery(name, ns_c_in, T_CAA); |
||
847 |
return 0; |
||
848 |
} |
||
849 |
|||
850 |
int CnameTraits::Send(QueryWrap<CnameTraits>* wrap, const char* name) { |
||
851 |
wrap->AresQuery(name, ns_c_in, ns_t_cname); |
||
852 |
return 0; |
||
853 |
} |
||
854 |
|||
855 |
1 |
int MxTraits::Send(QueryWrap<MxTraits>* wrap, const char* name) { |
|
856 |
1 |
wrap->AresQuery(name, ns_c_in, ns_t_mx); |
|
857 |
1 |
return 0; |
|
858 |
} |
||
859 |
|||
860 |
int NsTraits::Send(QueryWrap<NsTraits>* wrap, const char* name) { |
||
861 |
wrap->AresQuery(name, ns_c_in, ns_t_ns); |
||
862 |
return 0; |
||
863 |
} |
||
864 |
|||
865 |
int TxtTraits::Send(QueryWrap<TxtTraits>* wrap, const char* name) { |
||
866 |
wrap->AresQuery(name, ns_c_in, ns_t_txt); |
||
867 |
return 0; |
||
868 |
} |
||
869 |
|||
870 |
int SrvTraits::Send(QueryWrap<SrvTraits>* wrap, const char* name) { |
||
871 |
wrap->AresQuery(name, ns_c_in, ns_t_srv); |
||
872 |
return 0; |
||
873 |
} |
||
874 |
|||
875 |
int PtrTraits::Send(QueryWrap<PtrTraits>* wrap, const char* name) { |
||
876 |
wrap->AresQuery(name, ns_c_in, ns_t_ptr); |
||
877 |
return 0; |
||
878 |
} |
||
879 |
|||
880 |
int NaptrTraits::Send(QueryWrap<NaptrTraits>* wrap, const char* name) { |
||
881 |
wrap->AresQuery(name, ns_c_in, ns_t_naptr); |
||
882 |
return 0; |
||
883 |
} |
||
884 |
|||
885 |
2 |
int SoaTraits::Send(QueryWrap<SoaTraits>* wrap, const char* name) { |
|
886 |
2 |
wrap->AresQuery(name, ns_c_in, ns_t_soa); |
|
887 |
2 |
return 0; |
|
888 |
} |
||
889 |
|||
890 |
6 |
int AnyTraits::Parse( |
|
891 |
QueryAnyWrap* wrap, |
||
892 |
const std::unique_ptr<ResponseData>& response) { |
||
893 |
✗✓ | 6 |
if (UNLIKELY(response->is_host)) |
894 |
return ARES_EBADRESP; |
||
895 |
|||
896 |
6 |
unsigned char* buf = response->buf.data; |
|
897 |
6 |
int len = response->buf.size; |
|
898 |
|||
899 |
6 |
Environment* env = wrap->env(); |
|
900 |
12 |
HandleScope handle_scope(env->isolate()); |
|
901 |
6 |
Context::Scope context_scope(env->context()); |
|
902 |
|||
903 |
6 |
Local<Array> ret = Array::New(env->isolate()); |
|
904 |
int type, status, old_count; |
||
905 |
|||
906 |
/* Parse A records or CNAME records */ |
||
907 |
ares_addrttl addrttls[256]; |
||
908 |
6 |
int naddrttls = arraysize(addrttls); |
|
909 |
|||
910 |
6 |
type = ns_t_cname_or_a; |
|
911 |
6 |
status = ParseGeneralReply(env, |
|
912 |
buf, |
||
913 |
len, |
||
914 |
&type, |
||
915 |
ret, |
||
916 |
addrttls, |
||
917 |
&naddrttls); |
||
918 |
6 |
uint32_t a_count = ret->Length(); |
|
919 |
✓✓✓✗ |
6 |
if (status != ARES_SUCCESS && status != ARES_ENODATA) |
920 |
2 |
return status; |
|
921 |
|||
922 |
✓✗ | 4 |
if (type == ns_t_a) { |
923 |
✗✓ | 4 |
CHECK_EQ(static_cast<uint32_t>(naddrttls), a_count); |
924 |
✓✓ | 8 |
for (uint32_t i = 0; i < a_count; i++) { |
925 |
4 |
Local<Object> obj = Object::New(env->isolate()); |
|
926 |
4 |
obj->Set(env->context(), |
|
927 |
env->address_string(), |
||
928 |
16 |
ret->Get(env->context(), i).ToLocalChecked()).Check(); |
|
929 |
4 |
obj->Set(env->context(), |
|
930 |
env->ttl_string(), |
||
931 |
Integer::NewFromUnsigned( |
||
932 |
16 |
env->isolate(), addrttls[i].ttl)).Check(); |
|
933 |
4 |
obj->Set(env->context(), |
|
934 |
env->type_string(), |
||
935 |
16 |
env->dns_a_string()).Check(); |
|
936 |
8 |
ret->Set(env->context(), i, obj).Check(); |
|
937 |
} |
||
938 |
} else { |
||
939 |
for (uint32_t i = 0; i < a_count; i++) { |
||
940 |
Local<Object> obj = Object::New(env->isolate()); |
||
941 |
obj->Set(env->context(), |
||
942 |
env->value_string(), |
||
943 |
ret->Get(env->context(), i).ToLocalChecked()).Check(); |
||
944 |
obj->Set(env->context(), |
||
945 |
env->type_string(), |
||
946 |
env->dns_cname_string()).Check(); |
||
947 |
ret->Set(env->context(), i, obj).Check(); |
||
948 |
} |
||
949 |
} |
||
950 |
|||
951 |
/* Parse AAAA records */ |
||
952 |
ares_addr6ttl addr6ttls[256]; |
||
953 |
4 |
int naddr6ttls = arraysize(addr6ttls); |
|
954 |
|||
955 |
4 |
type = ns_t_aaaa; |
|
956 |
4 |
status = ParseGeneralReply(env, |
|
957 |
buf, |
||
958 |
len, |
||
959 |
&type, |
||
960 |
ret, |
||
961 |
addr6ttls, |
||
962 |
&naddr6ttls); |
||
963 |
4 |
uint32_t aaaa_count = ret->Length() - a_count; |
|
964 |
✗✓✗✗ |
4 |
if (status != ARES_SUCCESS && status != ARES_ENODATA) |
965 |
return status; |
||
966 |
|||
967 |
✗✓ | 4 |
CHECK_EQ(aaaa_count, static_cast<uint32_t>(naddr6ttls)); |
968 |
✗✓ | 4 |
CHECK_EQ(ret->Length(), a_count + aaaa_count); |
969 |
✓✓ | 12 |
for (uint32_t i = a_count; i < ret->Length(); i++) { |
970 |
4 |
Local<Object> obj = Object::New(env->isolate()); |
|
971 |
4 |
obj->Set(env->context(), |
|
972 |
env->address_string(), |
||
973 |
16 |
ret->Get(env->context(), i).ToLocalChecked()).Check(); |
|
974 |
4 |
obj->Set(env->context(), |
|
975 |
env->ttl_string(), |
||
976 |
Integer::NewFromUnsigned( |
||
977 |
16 |
env->isolate(), addr6ttls[i - a_count].ttl)).Check(); |
|
978 |
4 |
obj->Set(env->context(), |
|
979 |
env->type_string(), |
||
980 |
16 |
env->dns_aaaa_string()).Check(); |
|
981 |
8 |
ret->Set(env->context(), i, obj).Check(); |
|
982 |
} |
||
983 |
|||
984 |
/* Parse MX records */ |
||
985 |
4 |
status = ParseMxReply(env, buf, len, ret, true); |
|
986 |
✗✓✗✗ |
4 |
if (status != ARES_SUCCESS && status != ARES_ENODATA) |
987 |
return status; |
||
988 |
|||
989 |
/* Parse NS records */ |
||
990 |
4 |
type = ns_t_ns; |
|
991 |
4 |
old_count = ret->Length(); |
|
992 |
4 |
status = ParseGeneralReply(env, buf, len, &type, ret); |
|
993 |
✗✓✗✗ |
4 |
if (status != ARES_SUCCESS && status != ARES_ENODATA) |
994 |
return status; |
||
995 |
|||
996 |
✓✓ | 12 |
for (uint32_t i = old_count; i < ret->Length(); i++) { |
997 |
4 |
Local<Object> obj = Object::New(env->isolate()); |
|
998 |
4 |
obj->Set(env->context(), |
|
999 |
env->value_string(), |
||
1000 |
16 |
ret->Get(env->context(), i).ToLocalChecked()).Check(); |
|
1001 |
4 |
obj->Set(env->context(), |
|
1002 |
env->type_string(), |
||
1003 |
16 |
env->dns_ns_string()).Check(); |
|
1004 |
8 |
ret->Set(env->context(), i, obj).Check(); |
|
1005 |
} |
||
1006 |
|||
1007 |
/* Parse TXT records */ |
||
1008 |
4 |
status = ParseTxtReply(env, buf, len, ret, true); |
|
1009 |
✗✓✗✗ |
4 |
if (status != ARES_SUCCESS && status != ARES_ENODATA) |
1010 |
return status; |
||
1011 |
|||
1012 |
/* Parse SRV records */ |
||
1013 |
4 |
status = ParseSrvReply(env, buf, len, ret, true); |
|
1014 |
✗✓✗✗ |
4 |
if (status != ARES_SUCCESS && status != ARES_ENODATA) |
1015 |
return status; |
||
1016 |
|||
1017 |
/* Parse PTR records */ |
||
1018 |
4 |
type = ns_t_ptr; |
|
1019 |
4 |
old_count = ret->Length(); |
|
1020 |
4 |
status = ParseGeneralReply(env, buf, len, &type, ret); |
|
1021 |
✗✓✗✗ |
4 |
if (status != ARES_SUCCESS && status != ARES_ENODATA) |
1022 |
return status; |
||
1023 |
✓✓ | 12 |
for (uint32_t i = old_count; i < ret->Length(); i++) { |
1024 |
4 |
Local<Object> obj = Object::New(env->isolate()); |
|
1025 |
4 |
obj->Set(env->context(), |
|
1026 |
env->value_string(), |
||
1027 |
16 |
ret->Get(env->context(), i).ToLocalChecked()).Check(); |
|
1028 |
4 |
obj->Set(env->context(), |
|
1029 |
env->type_string(), |
||
1030 |
16 |
env->dns_ptr_string()).Check(); |
|
1031 |
8 |
ret->Set(env->context(), i, obj).Check(); |
|
1032 |
} |
||
1033 |
|||
1034 |
/* Parse NAPTR records */ |
||
1035 |
4 |
status = ParseNaptrReply(env, buf, len, ret, true); |
|
1036 |
✗✓✗✗ |
4 |
if (status != ARES_SUCCESS && status != ARES_ENODATA) |
1037 |
return status; |
||
1038 |
|||
1039 |
/* Parse SOA records */ |
||
1040 |
Local<Object> soa_record = Local<Object>(); |
||
1041 |
4 |
status = ParseSoaReply(env, buf, len, &soa_record); |
|
1042 |
✗✓✗✗ |
4 |
if (status != ARES_SUCCESS && status != ARES_ENODATA) |
1043 |
return status; |
||
1044 |
|||
1045 |
✓✗ | 4 |
if (!soa_record.IsEmpty()) |
1046 |
8 |
ret->Set(env->context(), ret->Length(), soa_record).Check(); |
|
1047 |
|||
1048 |
/* Parse CAA records */ |
||
1049 |
4 |
status = ParseCaaReply(env, buf, len, ret, true); |
|
1050 |
✗✓✗✗ |
4 |
if (status != ARES_SUCCESS && status != ARES_ENODATA) |
1051 |
return status; |
||
1052 |
|||
1053 |
4 |
wrap->CallOnComplete(ret); |
|
1054 |
4 |
return 0; |
|
1055 |
} |
||
1056 |
|||
1057 |
7 |
int ATraits::Parse( |
|
1058 |
QueryAWrap* wrap, |
||
1059 |
const std::unique_ptr<ResponseData>& response) { |
||
1060 |
✗✓ | 7 |
if (UNLIKELY(response->is_host)) |
1061 |
return ARES_EBADRESP; |
||
1062 |
|||
1063 |
7 |
unsigned char* buf = response->buf.data; |
|
1064 |
7 |
int len = response->buf.size; |
|
1065 |
|||
1066 |
7 |
Environment* env = wrap->env(); |
|
1067 |
14 |
HandleScope handle_scope(env->isolate()); |
|
1068 |
7 |
Context::Scope context_scope(env->context()); |
|
1069 |
|||
1070 |
ares_addrttl addrttls[256]; |
||
1071 |
7 |
int naddrttls = arraysize(addrttls), status; |
|
1072 |
7 |
Local<Array> ret = Array::New(env->isolate()); |
|
1073 |
|||
1074 |
7 |
int type = ns_t_a; |
|
1075 |
7 |
status = ParseGeneralReply(env, |
|
1076 |
buf, |
||
1077 |
len, |
||
1078 |
&type, |
||
1079 |
ret, |
||
1080 |
addrttls, |
||
1081 |
&naddrttls); |
||
1082 |
✗✓ | 7 |
if (status != ARES_SUCCESS) |
1083 |
return status; |
||
1084 |
|||
1085 |
7 |
Local<Array> ttls = AddrTTLToArray<ares_addrttl>(env, addrttls, naddrttls); |
|
1086 |
|||
1087 |
7 |
wrap->CallOnComplete(ret, ttls); |
|
1088 |
7 |
return 0; |
|
1089 |
} |
||
1090 |
|||
1091 |
2 |
int AaaaTraits::Parse( |
|
1092 |
QueryAaaaWrap* wrap, |
||
1093 |
const std::unique_ptr<ResponseData>& response) { |
||
1094 |
✗✓ | 2 |
if (UNLIKELY(response->is_host)) |
1095 |
return ARES_EBADRESP; |
||
1096 |
|||
1097 |
2 |
unsigned char* buf = response->buf.data; |
|
1098 |
2 |
int len = response->buf.size; |
|
1099 |
|||
1100 |
2 |
Environment* env = wrap->env(); |
|
1101 |
4 |
HandleScope handle_scope(env->isolate()); |
|
1102 |
2 |
Context::Scope context_scope(env->context()); |
|
1103 |
|||
1104 |
ares_addr6ttl addrttls[256]; |
||
1105 |
2 |
int naddrttls = arraysize(addrttls), status; |
|
1106 |
2 |
Local<Array> ret = Array::New(env->isolate()); |
|
1107 |
|||
1108 |
2 |
int type = ns_t_aaaa; |
|
1109 |
2 |
status = ParseGeneralReply(env, |
|
1110 |
buf, |
||
1111 |
len, |
||
1112 |
&type, |
||
1113 |
ret, |
||
1114 |
addrttls, |
||
1115 |
&naddrttls); |
||
1116 |
✗✓ | 2 |
if (status != ARES_SUCCESS) |
1117 |
return status; |
||
1118 |
|||
1119 |
2 |
Local<Array> ttls = AddrTTLToArray<ares_addr6ttl>(env, addrttls, naddrttls); |
|
1120 |
|||
1121 |
2 |
wrap->CallOnComplete(ret, ttls); |
|
1122 |
2 |
return 0; |
|
1123 |
} |
||
1124 |
|||
1125 |
int CaaTraits::Parse( |
||
1126 |
QueryCaaWrap* wrap, |
||
1127 |
const std::unique_ptr<ResponseData>& response) { |
||
1128 |
if (UNLIKELY(response->is_host)) |
||
1129 |
return ARES_EBADRESP; |
||
1130 |
|||
1131 |
unsigned char* buf = response->buf.data; |
||
1132 |
int len = response->buf.size; |
||
1133 |
|||
1134 |
Environment* env = wrap->env(); |
||
1135 |
HandleScope handle_scope(env->isolate()); |
||
1136 |
Context::Scope context_scope(env->context()); |
||
1137 |
|||
1138 |
Local<Array> ret = Array::New(env->isolate()); |
||
1139 |
int status = ParseCaaReply(env, buf, len, ret); |
||
1140 |
if (status != ARES_SUCCESS) |
||
1141 |
return status; |
||
1142 |
|||
1143 |
wrap->CallOnComplete(ret); |
||
1144 |
return 0; |
||
1145 |
} |
||
1146 |
|||
1147 |
int CnameTraits::Parse( |
||
1148 |
QueryCnameWrap* wrap, |
||
1149 |
const std::unique_ptr<ResponseData>& response) { |
||
1150 |
if (UNLIKELY(response->is_host)) |
||
1151 |
return ARES_EBADRESP; |
||
1152 |
|||
1153 |
unsigned char* buf = response->buf.data; |
||
1154 |
int len = response->buf.size; |
||
1155 |
|||
1156 |
Environment* env = wrap->env(); |
||
1157 |
HandleScope handle_scope(env->isolate()); |
||
1158 |
Context::Scope context_scope(env->context()); |
||
1159 |
|||
1160 |
Local<Array> ret = Array::New(env->isolate()); |
||
1161 |
int type = ns_t_cname; |
||
1162 |
int status = ParseGeneralReply(env, buf, len, &type, ret); |
||
1163 |
if (status != ARES_SUCCESS) |
||
1164 |
return status; |
||
1165 |
|||
1166 |
wrap->CallOnComplete(ret); |
||
1167 |
return 0; |
||
1168 |
} |
||
1169 |
|||
1170 |
int MxTraits::Parse( |
||
1171 |
QueryMxWrap* wrap, |
||
1172 |
const std::unique_ptr<ResponseData>& response) { |
||
1173 |
if (UNLIKELY(response->is_host)) |
||
1174 |
return ARES_EBADRESP; |
||
1175 |
|||
1176 |
unsigned char* buf = response->buf.data; |
||
1177 |
int len = response->buf.size; |
||
1178 |
|||
1179 |
Environment* env = wrap->env(); |
||
1180 |
HandleScope handle_scope(env->isolate()); |
||
1181 |
Context::Scope context_scope(env->context()); |
||
1182 |
|||
1183 |
Local<Array> mx_records = Array::New(env->isolate()); |
||
1184 |
int status = ParseMxReply(env, buf, len, mx_records); |
||
1185 |
|||
1186 |
if (status != ARES_SUCCESS) |
||
1187 |
return status; |
||
1188 |
|||
1189 |
wrap->CallOnComplete(mx_records); |
||
1190 |
return 0; |
||
1191 |
} |
||
1192 |
|||
1193 |
int NsTraits::Parse( |
||
1194 |
QueryNsWrap* wrap, |
||
1195 |
const std::unique_ptr<ResponseData>& response) { |
||
1196 |
if (UNLIKELY(response->is_host)) |
||
1197 |
return ARES_EBADRESP; |
||
1198 |
|||
1199 |
unsigned char* buf = response->buf.data; |
||
1200 |
int len = response->buf.size; |
||
1201 |
|||
1202 |
Environment* env = wrap->env(); |
||
1203 |
HandleScope handle_scope(env->isolate()); |
||
1204 |
Context::Scope context_scope(env->context()); |
||
1205 |
|||
1206 |
int type = ns_t_ns; |
||
1207 |
Local<Array> names = Array::New(env->isolate()); |
||
1208 |
int status = ParseGeneralReply(env, buf, len, &type, names); |
||
1209 |
if (status != ARES_SUCCESS) |
||
1210 |
return status; |
||
1211 |
|||
1212 |
wrap->CallOnComplete(names); |
||
1213 |
return 0; |
||
1214 |
} |
||
1215 |
|||
1216 |
int TxtTraits::Parse( |
||
1217 |
QueryTxtWrap* wrap, |
||
1218 |
const std::unique_ptr<ResponseData>& response) { |
||
1219 |
if (UNLIKELY(response->is_host)) |
||
1220 |
return ARES_EBADRESP; |
||
1221 |
|||
1222 |
unsigned char* buf = response->buf.data; |
||
1223 |
int len = response->buf.size; |
||
1224 |
|||
1225 |
Environment* env = wrap->env(); |
||
1226 |
HandleScope handle_scope(env->isolate()); |
||
1227 |
Context::Scope context_scope(env->context()); |
||
1228 |
|||
1229 |
Local<Array> txt_records = Array::New(env->isolate()); |
||
1230 |
int status = ParseTxtReply(env, buf, len, txt_records); |
||
1231 |
if (status != ARES_SUCCESS) |
||
1232 |
return status; |
||
1233 |
|||
1234 |
wrap->CallOnComplete(txt_records); |
||
1235 |
return 0; |
||
1236 |
} |
||
1237 |
|||
1238 |
int SrvTraits::Parse( |
||
1239 |
QuerySrvWrap* wrap, |
||
1240 |
const std::unique_ptr<ResponseData>& response) { |
||
1241 |
if (UNLIKELY(response->is_host)) |
||
1242 |
return ARES_EBADRESP; |
||
1243 |
|||
1244 |
unsigned char* buf = response->buf.data; |
||
1245 |
int len = response->buf.size; |
||
1246 |
|||
1247 |
Environment* env = wrap->env(); |
||
1248 |
HandleScope handle_scope(env->isolate()); |
||
1249 |
Context::Scope context_scope(env->context()); |
||
1250 |
|||
1251 |
Local<Array> srv_records = Array::New(env->isolate()); |
||
1252 |
int status = ParseSrvReply(env, buf, len, srv_records); |
||
1253 |
if (status != ARES_SUCCESS) |
||
1254 |
return status; |
||
1255 |
|||
1256 |
wrap->CallOnComplete(srv_records); |
||
1257 |
return 0; |
||
1258 |
} |
||
1259 |
|||
1260 |
int PtrTraits::Parse( |
||
1261 |
QueryPtrWrap* wrap, |
||
1262 |
const std::unique_ptr<ResponseData>& response) { |
||
1263 |
if (UNLIKELY(response->is_host)) |
||
1264 |
return ARES_EBADRESP; |
||
1265 |
|||
1266 |
unsigned char* buf = response->buf.data; |
||
1267 |
int len = response->buf.size; |
||
1268 |
|||
1269 |
Environment* env = wrap->env(); |
||
1270 |
HandleScope handle_scope(env->isolate()); |
||
1271 |
Context::Scope context_scope(env->context()); |
||
1272 |
|||
1273 |
int type = ns_t_ptr; |
||
1274 |
Local<Array> aliases = Array::New(env->isolate()); |
||
1275 |
|||
1276 |
int status = ParseGeneralReply(env, buf, len, &type, aliases); |
||
1277 |
if (status != ARES_SUCCESS) |
||
1278 |
return status; |
||
1279 |
|||
1280 |
wrap->CallOnComplete(aliases); |
||
1281 |
return 0; |
||
1282 |
} |
||
1283 |
|||
1284 |
int NaptrTraits::Parse( |
||
1285 |
QueryNaptrWrap* wrap, |
||
1286 |
const std::unique_ptr<ResponseData>& response) { |
||
1287 |
if (UNLIKELY(response->is_host)) |
||
1288 |
return ARES_EBADRESP; |
||
1289 |
|||
1290 |
unsigned char* buf = response->buf.data; |
||
1291 |
int len = response->buf.size; |
||
1292 |
|||
1293 |
Environment* env = wrap->env(); |
||
1294 |
HandleScope handle_scope(env->isolate()); |
||
1295 |
Context::Scope context_scope(env->context()); |
||
1296 |
|||
1297 |
Local<Array> naptr_records = Array::New(env->isolate()); |
||
1298 |
int status = ParseNaptrReply(env, buf, len, naptr_records); |
||
1299 |
if (status != ARES_SUCCESS) |
||
1300 |
return status; |
||
1301 |
|||
1302 |
wrap->CallOnComplete(naptr_records); |
||
1303 |
return 0; |
||
1304 |
} |
||
1305 |
|||
1306 |
2 |
int SoaTraits::Parse( |
|
1307 |
QuerySoaWrap* wrap, |
||
1308 |
const std::unique_ptr<ResponseData>& response) { |
||
1309 |
✗✓ | 2 |
if (UNLIKELY(response->is_host)) |
1310 |
return ARES_EBADRESP; |
||
1311 |
|||
1312 |
2 |
unsigned char* buf = response->buf.data; |
|
1313 |
2 |
int len = response->buf.size; |
|
1314 |
|||
1315 |
2 |
Environment* env = wrap->env(); |
|
1316 |
4 |
HandleScope handle_scope(env->isolate()); |
|
1317 |
2 |
Context::Scope context_scope(env->context()); |
|
1318 |
|||
1319 |
ares_soa_reply* soa_out; |
||
1320 |
2 |
int status = ares_parse_soa_reply(buf, len, &soa_out); |
|
1321 |
|||
1322 |
✗✓ | 2 |
if (status != ARES_SUCCESS) |
1323 |
return status; |
||
1324 |
|||
1325 |
2 |
Local<Object> soa_record = Object::New(env->isolate()); |
|
1326 |
|||
1327 |
2 |
soa_record->Set(env->context(), |
|
1328 |
env->nsname_string(), |
||
1329 |
8 |
OneByteString(env->isolate(), soa_out->nsname)).Check(); |
|
1330 |
2 |
soa_record->Set(env->context(), |
|
1331 |
env->hostmaster_string(), |
||
1332 |
8 |
OneByteString(env->isolate(), soa_out->hostmaster)).Check(); |
|
1333 |
2 |
soa_record->Set(env->context(), |
|
1334 |
env->serial_string(), |
||
1335 |
Integer::NewFromUnsigned( |
||
1336 |
8 |
env->isolate(), soa_out->serial)).Check(); |
|
1337 |
2 |
soa_record->Set(env->context(), |
|
1338 |
env->refresh_string(), |
||
1339 |
8 |
Integer::New(env->isolate(), soa_out->refresh)).Check(); |
|
1340 |
2 |
soa_record->Set(env->context(), |
|
1341 |
env->retry_string(), |
||
1342 |
8 |
Integer::New(env->isolate(), soa_out->retry)).Check(); |
|
1343 |
2 |
soa_record->Set(env->context(), |
|
1344 |
env->expire_string(), |
||
1345 |
8 |
Integer::New(env->isolate(), soa_out->expire)).Check(); |
|
1346 |
2 |
soa_record->Set(env->context(), |
|
1347 |
env->minttl_string(), |
||
1348 |
Integer::NewFromUnsigned( |
||
1349 |
6 |
env->isolate(), soa_out->minttl)).Check(); |
|
1350 |
|||
1351 |
2 |
ares_free_data(soa_out); |
|
1352 |
|||
1353 |
2 |
wrap->CallOnComplete(soa_record); |
|
1354 |
2 |
return 0; |
|
1355 |
} |
||
1356 |
|||
1357 |
3 |
int ReverseTraits::Send(GetHostByAddrWrap* wrap, const char* name) { |
|
1358 |
int length, family; |
||
1359 |
char address_buffer[sizeof(struct in6_addr)]; |
||
1360 |
|||
1361 |
✓✗ | 3 |
if (uv_inet_pton(AF_INET, name, &address_buffer) == 0) { |
1362 |
3 |
length = sizeof(struct in_addr); |
|
1363 |
3 |
family = AF_INET; |
|
1364 |
} else if (uv_inet_pton(AF_INET6, name, &address_buffer) == 0) { |
||
1365 |
length = sizeof(struct in6_addr); |
||
1366 |
family = AF_INET6; |
||
1367 |
} else { |
||
1368 |
return UV_EINVAL; // So errnoException() reports a proper error. |
||
1369 |
} |
||
1370 |
|||
1371 |
✓✓✗✓ ✗✗ |
5 |
TRACE_EVENT_NESTABLE_ASYNC_BEGIN2( |
1372 |
TRACING_CATEGORY_NODE2(dns, native), "reverse", wrap, |
||
1373 |
"name", TRACE_STR_COPY(name), |
||
1374 |
"family", family == AF_INET ? "ipv4" : "ipv6"); |
||
1375 |
|||
1376 |
6 |
ares_gethostbyaddr( |
|
1377 |
3 |
wrap->channel()->cares_channel(), |
|
1378 |
address_buffer, |
||
1379 |
length, |
||
1380 |
family, |
||
1381 |
GetHostByAddrWrap::Callback, |
||
1382 |
wrap->MakeCallbackPointer()); |
||
1383 |
3 |
return 0; |
|
1384 |
} |
||
1385 |
|||
1386 |
2 |
int ReverseTraits::Parse( |
|
1387 |
GetHostByAddrWrap* wrap, |
||
1388 |
const std::unique_ptr<ResponseData>& response) { |
||
1389 |
✗✓ | 2 |
if (UNLIKELY(!response->is_host)) |
1390 |
return ARES_EBADRESP; |
||
1391 |
|||
1392 |
2 |
struct hostent* host = response->host.get(); |
|
1393 |
|||
1394 |
2 |
Environment* env = wrap->env(); |
|
1395 |
4 |
HandleScope handle_scope(env->isolate()); |
|
1396 |
4 |
Context::Scope context_scope(env->context()); |
|
1397 |
4 |
wrap->CallOnComplete(HostentToNames(env, host)); |
|
1398 |
2 |
return 0; |
|
1399 |
} |
||
1400 |
|||
1401 |
namespace { |
||
1402 |
template <class Wrap> |
||
1403 |
106 |
static void Query(const FunctionCallbackInfo<Value>& args) { |
|
1404 |
106 |
Environment* env = Environment::GetCurrent(args); |
|
1405 |
ChannelWrap* channel; |
||
1406 |
✗✓ | 106 |
ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder()); |
1407 |
|||
1408 |
✗✓ | 106 |
CHECK_EQ(false, args.IsConstructCall()); |
1409 |
✗✓ | 106 |
CHECK(args[0]->IsObject()); |
1410 |
✗✓ | 212 |
CHECK(args[1]->IsString()); |
1411 |
|||
1412 |
✓✗ | 212 |
Local<Object> req_wrap_obj = args[0].As<Object>(); |
1413 |
106 |
Local<String> string = args[1].As<String>(); |
|
1414 |
212 |
auto wrap = std::make_unique<Wrap>(channel, req_wrap_obj); |
|
1415 |
|||
1416 |
106 |
node::Utf8Value name(env->isolate(), string); |
|
1417 |
106 |
channel->ModifyActivityQueryCount(1); |
|
1418 |
106 |
int err = wrap->Send(*name); |
|
1419 |
✗✓ | 106 |
if (err) { |
1420 |
channel->ModifyActivityQueryCount(-1); |
||
1421 |
} else { |
||
1422 |
// Release ownership of the pointer allowing the ownership to be transferred |
||
1423 |
106 |
USE(wrap.release()); |
|
1424 |
} |
||
1425 |
|||
1426 |
212 |
args.GetReturnValue().Set(err); |
|
1427 |
} |
||
1428 |
|||
1429 |
|||
1430 |
5293 |
void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) { |
|
1431 |
10584 |
auto cleanup = OnScopeLeave([&]() { uv_freeaddrinfo(res); }); |
|
1432 |
std::unique_ptr<GetAddrInfoReqWrap> req_wrap { |
||
1433 |
5293 |
static_cast<GetAddrInfoReqWrap*>(req->data)}; |
|
1434 |
5293 |
Environment* env = req_wrap->env(); |
|
1435 |
|||
1436 |
5293 |
HandleScope handle_scope(env->isolate()); |
|
1437 |
5293 |
Context::Scope context_scope(env->context()); |
|
1438 |
|||
1439 |
Local<Value> argv[] = { |
||
1440 |
Integer::New(env->isolate(), status), |
||
1441 |
Null(env->isolate()) |
||
1442 |
10586 |
}; |
|
1443 |
|||
1444 |
5293 |
uint32_t n = 0; |
|
1445 |
5293 |
const bool verbatim = req_wrap->verbatim(); |
|
1446 |
|||
1447 |
✓✓ | 5293 |
if (status == 0) { |
1448 |
5284 |
Local<Array> results = Array::New(env->isolate()); |
|
1449 |
|||
1450 |
5304 |
auto add = [&] (bool want_ipv4, bool want_ipv6) -> Maybe<bool> { |
|
1451 |
✓✓ | 21209 |
for (auto p = res; p != nullptr; p = p->ai_next) { |
1452 |
✗✓ | 15905 |
CHECK_EQ(p->ai_socktype, SOCK_STREAM); |
1453 |
|||
1454 |
const char* addr; |
||
1455 |
✓✓✓✓ |
15905 |
if (want_ipv4 && p->ai_family == AF_INET) { |
1456 |
5815 |
addr = reinterpret_cast<char*>( |
|
1457 |
5815 |
&(reinterpret_cast<struct sockaddr_in*>(p->ai_addr)->sin_addr)); |
|
1458 |
✓✓✓✓ |
10090 |
} else if (want_ipv6 && p->ai_family == AF_INET6) { |
1459 |
10042 |
addr = reinterpret_cast<char*>( |
|
1460 |
10042 |
&(reinterpret_cast<struct sockaddr_in6*>(p->ai_addr)->sin6_addr)); |
|
1461 |
} else { |
||
1462 |
48 |
continue; |
|
1463 |
} |
||
1464 |
|||
1465 |
char ip[INET6_ADDRSTRLEN]; |
||
1466 |
✗✓ | 15857 |
if (uv_inet_ntop(p->ai_family, addr, ip, sizeof(ip))) |
1467 |
continue; |
||
1468 |
|||
1469 |
15857 |
Local<String> s = OneByteString(env->isolate(), ip); |
|
1470 |
✗✓ | 31714 |
if (results->Set(env->context(), n, s).IsNothing()) |
1471 |
return Nothing<bool>(); |
||
1472 |
15857 |
n++; |
|
1473 |
} |
||
1474 |
5304 |
return Just(true); |
|
1475 |
5284 |
}; |
|
1476 |
|||
1477 |
✗✓ | 10568 |
if (add(true, verbatim).IsNothing()) |
1478 |
return; |
||
1479 |
✓✓ | 5284 |
if (verbatim == false) { |
1480 |
✗✓ | 40 |
if (add(false, true).IsNothing()) |
1481 |
return; |
||
1482 |
} |
||
1483 |
|||
1484 |
// No responses were found to return |
||
1485 |
✗✓ | 5284 |
if (n == 0) { |
1486 |
argv[0] = Integer::New(env->isolate(), UV_EAI_NODATA); |
||
1487 |
} |
||
1488 |
|||
1489 |
5284 |
argv[1] = results; |
|
1490 |
} |
||
1491 |
|||
1492 |
✓✓✗✓ |
6151 |
TRACE_EVENT_NESTABLE_ASYNC_END2( |
1493 |
TRACING_CATEGORY_NODE2(dns, native), "lookup", req_wrap.get(), |
||
1494 |
"count", n, "verbatim", verbatim); |
||
1495 |
|||
1496 |
// Make the callback into JavaScript |
||
1497 |
5293 |
req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv); |
|
1498 |
} |
||
1499 |
|||
1500 |
|||
1501 |
6 |
void AfterGetNameInfo(uv_getnameinfo_t* req, |
|
1502 |
int status, |
||
1503 |
const char* hostname, |
||
1504 |
const char* service) { |
||
1505 |
std::unique_ptr<GetNameInfoReqWrap> req_wrap { |
||
1506 |
12 |
static_cast<GetNameInfoReqWrap*>(req->data)}; |
|
1507 |
6 |
Environment* env = req_wrap->env(); |
|
1508 |
|||
1509 |
12 |
HandleScope handle_scope(env->isolate()); |
|
1510 |
6 |
Context::Scope context_scope(env->context()); |
|
1511 |
|||
1512 |
Local<Value> argv[] = { |
||
1513 |
Integer::New(env->isolate(), status), |
||
1514 |
Null(env->isolate()), |
||
1515 |
Null(env->isolate()) |
||
1516 |
18 |
}; |
|
1517 |
|||
1518 |
✓✓ | 6 |
if (status == 0) { |
1519 |
// Success |
||
1520 |
5 |
Local<String> js_hostname = OneByteString(env->isolate(), hostname); |
|
1521 |
5 |
Local<String> js_service = OneByteString(env->isolate(), service); |
|
1522 |
5 |
argv[1] = js_hostname; |
|
1523 |
5 |
argv[2] = js_service; |
|
1524 |
} |
||
1525 |
|||
1526 |
✓✓✗✓ |
10 |
TRACE_EVENT_NESTABLE_ASYNC_END2( |
1527 |
TRACING_CATEGORY_NODE2(dns, native), "lookupService", req_wrap.get(), |
||
1528 |
"hostname", TRACE_STR_COPY(hostname), |
||
1529 |
"service", TRACE_STR_COPY(service)); |
||
1530 |
|||
1531 |
// Make the callback into JavaScript |
||
1532 |
6 |
req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv); |
|
1533 |
6 |
} |
|
1534 |
|||
1535 |
using ParseIPResult = |
||
1536 |
decltype(static_cast<ares_addr_port_node*>(nullptr)->addr); |
||
1537 |
|||
1538 |
27 |
int ParseIP(const char* ip, ParseIPResult* result = nullptr) { |
|
1539 |
ParseIPResult tmp; |
||
1540 |
✗✓ | 27 |
if (result == nullptr) result = &tmp; |
1541 |
✓✓ | 27 |
if (0 == uv_inet_pton(AF_INET, ip, result)) return 4; |
1542 |
✓✓ | 10 |
if (0 == uv_inet_pton(AF_INET6, ip, result)) return 6; |
1543 |
1 |
return 0; |
|
1544 |
} |
||
1545 |
|||
1546 |
27 |
void CanonicalizeIP(const FunctionCallbackInfo<Value>& args) { |
|
1547 |
✓✗ | 27 |
Isolate* isolate = args.GetIsolate(); |
1548 |
27 |
node::Utf8Value ip(isolate, args[0]); |
|
1549 |
|||
1550 |
ParseIPResult result; |
||
1551 |
27 |
const int rc = ParseIP(*ip, &result); |
|
1552 |
✓✓ | 27 |
if (rc == 0) return; |
1553 |
|||
1554 |
char canonical_ip[INET6_ADDRSTRLEN]; |
||
1555 |
✓✓ | 26 |
const int af = (rc == 4 ? AF_INET : AF_INET6); |
1556 |
✗✓ | 26 |
CHECK_EQ(0, uv_inet_ntop(af, &result, canonical_ip, sizeof(canonical_ip))); |
1557 |
26 |
Local<String> val = String::NewFromUtf8(isolate, canonical_ip) |
|
1558 |
26 |
.ToLocalChecked(); |
|
1559 |
52 |
args.GetReturnValue().Set(val); |
|
1560 |
} |
||
1561 |
|||
1562 |
5294 |
void GetAddrInfo(const FunctionCallbackInfo<Value>& args) { |
|
1563 |
✓✗ | 5294 |
Environment* env = Environment::GetCurrent(args); |
1564 |
|||
1565 |
✗✓ | 5294 |
CHECK(args[0]->IsObject()); |
1566 |
✗✓ | 10588 |
CHECK(args[1]->IsString()); |
1567 |
✗✓ | 5294 |
CHECK(args[2]->IsInt32()); |
1568 |
✗✓ | 5294 |
CHECK(args[4]->IsBoolean()); |
1569 |
✓✗ | 10588 |
Local<Object> req_wrap_obj = args[0].As<Object>(); |
1570 |
10588 |
node::Utf8Value hostname(env->isolate(), args[1]); |
|
1571 |
|||
1572 |
✓✗ | 5294 |
int32_t flags = 0; |
1573 |
✓✗ | 5294 |
if (args[3]->IsInt32()) { |
1574 |
10588 |
flags = args[3].As<Int32>()->Value(); |
|
1575 |
} |
||
1576 |
|||
1577 |
int family; |
||
1578 |
|||
1579 |
✓✓✓✗ |
10588 |
switch (args[2].As<Int32>()->Value()) { |
1580 |
5031 |
case 0: |
|
1581 |
5031 |
family = AF_UNSPEC; |
|
1582 |
5031 |
break; |
|
1583 |
258 |
case 4: |
|
1584 |
258 |
family = AF_INET; |
|
1585 |
258 |
break; |
|
1586 |
5 |
case 6: |
|
1587 |
5 |
family = AF_INET6; |
|
1588 |
5 |
break; |
|
1589 |
default: |
||
1590 |
CHECK(0 && "bad address family"); |
||
1591 |
} |
||
1592 |
|||
1593 |
auto req_wrap = std::make_unique<GetAddrInfoReqWrap>(env, |
||
1594 |
req_wrap_obj, |
||
1595 |
5294 |
args[4]->IsTrue()); |
|
1596 |
|||
1597 |
struct addrinfo hints; |
||
1598 |
5294 |
memset(&hints, 0, sizeof(hints)); |
|
1599 |
5294 |
hints.ai_family = family; |
|
1600 |
5294 |
hints.ai_socktype = SOCK_STREAM; |
|
1601 |
5294 |
hints.ai_flags = flags; |
|
1602 |
|||
1603 |
✓✓✗✓ ✗✗✗✗ |
6153 |
TRACE_EVENT_NESTABLE_ASYNC_BEGIN2( |
1604 |
TRACING_CATEGORY_NODE2(dns, native), "lookup", req_wrap.get(), |
||
1605 |
"hostname", TRACE_STR_COPY(*hostname), |
||
1606 |
"family", |
||
1607 |
family == AF_INET ? "ipv4" : family == AF_INET6 ? "ipv6" : "unspec"); |
||
1608 |
|||
1609 |
5294 |
int err = req_wrap->Dispatch(uv_getaddrinfo, |
|
1610 |
AfterGetAddrInfo, |
||
1611 |
*hostname, |
||
1612 |
nullptr, |
||
1613 |
&hints); |
||
1614 |
✓✗ | 5294 |
if (err == 0) |
1615 |
// Release ownership of the pointer allowing the ownership to be transferred |
||
1616 |
5294 |
USE(req_wrap.release()); |
|
1617 |
|||
1618 |
10588 |
args.GetReturnValue().Set(err); |
|
1619 |
5294 |
} |
|
1620 |
|||
1621 |
|||
1622 |
6 |
void GetNameInfo(const FunctionCallbackInfo<Value>& args) { |
|
1623 |
✓✗ | 6 |
Environment* env = Environment::GetCurrent(args); |
1624 |
|||
1625 |
✗✓ | 6 |
CHECK(args[0]->IsObject()); |
1626 |
✗✓ | 12 |
CHECK(args[1]->IsString()); |
1627 |
✗✓ | 6 |
CHECK(args[2]->IsUint32()); |
1628 |
✓✗ | 12 |
Local<Object> req_wrap_obj = args[0].As<Object>(); |
1629 |
12 |
node::Utf8Value ip(env->isolate(), args[1]); |
|
1630 |
6 |
const unsigned port = args[2]->Uint32Value(env->context()).FromJust(); |
|
1631 |
struct sockaddr_storage addr; |
||
1632 |
|||
1633 |
✓✓✗✓ ✗✓ |
6 |
CHECK(uv_ip4_addr(*ip, port, reinterpret_cast<sockaddr_in*>(&addr)) == 0 || |
1634 |
uv_ip6_addr(*ip, port, reinterpret_cast<sockaddr_in6*>(&addr)) == 0); |
||
1635 |
|||
1636 |
6 |
auto req_wrap = std::make_unique<GetNameInfoReqWrap>(env, req_wrap_obj); |
|
1637 |
|||
1638 |
✓✓✗✓ |
10 |
TRACE_EVENT_NESTABLE_ASYNC_BEGIN2( |
1639 |
TRACING_CATEGORY_NODE2(dns, native), "lookupService", req_wrap.get(), |
||
1640 |
"ip", TRACE_STR_COPY(*ip), "port", port); |
||
1641 |
|||
1642 |
6 |
int err = req_wrap->Dispatch(uv_getnameinfo, |
|
1643 |
AfterGetNameInfo, |
||
1644 |
reinterpret_cast<struct sockaddr*>(&addr), |
||
1645 |
NI_NAMEREQD); |
||
1646 |
✓✗ | 6 |
if (err == 0) |
1647 |
// Release ownership of the pointer allowing the ownership to be transferred |
||
1648 |
6 |
USE(req_wrap.release()); |
|
1649 |
|||
1650 |
12 |
args.GetReturnValue().Set(err); |
|
1651 |
6 |
} |
|
1652 |
|||
1653 |
|||
1654 |
66 |
void GetServers(const FunctionCallbackInfo<Value>& args) { |
|
1655 |
66 |
Environment* env = Environment::GetCurrent(args); |
|
1656 |
ChannelWrap* channel; |
||
1657 |
✗✓ | 66 |
ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder()); |
1658 |
|||
1659 |
66 |
Local<Array> server_array = Array::New(env->isolate()); |
|
1660 |
|||
1661 |
ares_addr_port_node* servers; |
||
1662 |
|||
1663 |
66 |
int r = ares_get_servers_ports(channel->cares_channel(), &servers); |
|
1664 |
✗✓ | 66 |
CHECK_EQ(r, ARES_SUCCESS); |
1665 |
132 |
auto cleanup = OnScopeLeave([&]() { ares_free_data(servers); }); |
|
1666 |
|||
1667 |
66 |
ares_addr_port_node* cur = servers; |
|
1668 |
|||
1669 |
✓✓ | 143 |
for (uint32_t i = 0; cur != nullptr; ++i, cur = cur->next) { |
1670 |
char ip[INET6_ADDRSTRLEN]; |
||
1671 |
|||
1672 |
77 |
const void* caddr = static_cast<const void*>(&cur->addr); |
|
1673 |
77 |
int err = uv_inet_ntop(cur->family, caddr, ip, sizeof(ip)); |
|
1674 |
✗✓ | 77 |
CHECK_EQ(err, 0); |
1675 |
|||
1676 |
Local<Value> ret[] = { |
||
1677 |
OneByteString(env->isolate(), ip), |
||
1678 |
Integer::New(env->isolate(), cur->udp_port) |
||
1679 |
231 |
}; |
|
1680 |
|||
1681 |
231 |
if (server_array->Set(env->context(), i, |
|
1682 |
154 |
Array::New(env->isolate(), ret, arraysize(ret))) |
|
1683 |
✗✓ | 77 |
.IsNothing()) { |
1684 |
return; |
||
1685 |
} |
||
1686 |
} |
||
1687 |
|||
1688 |
132 |
args.GetReturnValue().Set(server_array); |
|
1689 |
} |
||
1690 |
|||
1691 |
|||
1692 |
28 |
void SetServers(const FunctionCallbackInfo<Value>& args) { |
|
1693 |
28 |
Environment* env = Environment::GetCurrent(args); |
|
1694 |
ChannelWrap* channel; |
||
1695 |
✗✓ | 32 |
ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder()); |
1696 |
|||
1697 |
✓✓ | 28 |
if (channel->active_query_count()) { |
1698 |
4 |
return args.GetReturnValue().Set(DNS_ESETSRVPENDING); |
|
1699 |
} |
||
1700 |
|||
1701 |
✗✓ | 26 |
CHECK(args[0]->IsArray()); |
1702 |
|||
1703 |
52 |
Local<Array> arr = args[0].As<Array>(); |
|
1704 |
|||
1705 |
26 |
uint32_t len = arr->Length(); |
|
1706 |
|||
1707 |
✓✓ | 26 |
if (len == 0) { |
1708 |
2 |
int rv = ares_set_servers(channel->cares_channel(), nullptr); |
|
1709 |
4 |
return args.GetReturnValue().Set(rv); |
|
1710 |
} |
||
1711 |
|||
1712 |
24 |
std::vector<ares_addr_port_node> servers(len); |
|
1713 |
24 |
ares_addr_port_node* last = nullptr; |
|
1714 |
|||
1715 |
int err; |
||
1716 |
|||
1717 |
✓✓ | 59 |
for (uint32_t i = 0; i < len; i++) { |
1718 |
✗✓ | 70 |
CHECK(arr->Get(env->context(), i).ToLocalChecked()->IsArray()); |
1719 |
|||
1720 |
105 |
Local<Array> elm = arr->Get(env->context(), i).ToLocalChecked().As<Array>(); |
|
1721 |
|||
1722 |
✗✓ | 105 |
CHECK(elm->Get(env->context(), |
1723 |
0).ToLocalChecked()->Int32Value(env->context()).FromJust()); |
||
1724 |
✗✓ | 105 |
CHECK(elm->Get(env->context(), 1).ToLocalChecked()->IsString()); |
1725 |
✗✓ | 105 |
CHECK(elm->Get(env->context(), |
1726 |
2).ToLocalChecked()->Int32Value(env->context()).FromJust()); |
||
1727 |
|||
1728 |
35 |
int fam = elm->Get(env->context(), 0) |
|
1729 |
70 |
.ToLocalChecked()->Int32Value(env->context()).FromJust(); |
|
1730 |
node::Utf8Value ip(env->isolate(), |
||
1731 |
70 |
elm->Get(env->context(), 1).ToLocalChecked()); |
|
1732 |
35 |
int port = elm->Get(env->context(), 2) |
|
1733 |
35 |
.ToLocalChecked()->Int32Value(env->context()).FromJust(); |
|
1734 |
|||
1735 |
35 |
ares_addr_port_node* cur = &servers[i]; |
|
1736 |
|||
1737 |
35 |
cur->tcp_port = cur->udp_port = port; |
|
1738 |
✓✓✗ | 35 |
switch (fam) { |
1739 |
28 |
case 4: |
|
1740 |
28 |
cur->family = AF_INET; |
|
1741 |
28 |
err = uv_inet_pton(AF_INET, *ip, &cur->addr); |
|
1742 |
28 |
break; |
|
1743 |
7 |
case 6: |
|
1744 |
7 |
cur->family = AF_INET6; |
|
1745 |
7 |
err = uv_inet_pton(AF_INET6, *ip, &cur->addr); |
|
1746 |
7 |
break; |
|
1747 |
default: |
||
1748 |
CHECK(0 && "Bad address family."); |
||
1749 |
} |
||
1750 |
|||
1751 |
✗✓ | 35 |
if (err) |
1752 |
break; |
||
1753 |
|||
1754 |
35 |
cur->next = nullptr; |
|
1755 |
|||
1756 |
✓✓ | 35 |
if (last != nullptr) |
1757 |
11 |
last->next = cur; |
|
1758 |
|||
1759 |
35 |
last = cur; |
|
1760 |
} |
||
1761 |
|||
1762 |
✓✗ | 24 |
if (err == 0) |
1763 |
24 |
err = ares_set_servers_ports(channel->cares_channel(), &servers[0]); |
|
1764 |
else |
||
1765 |
err = ARES_EBADSTR; |
||
1766 |
|||
1767 |
✓✗ | 24 |
if (err == ARES_SUCCESS) |
1768 |
24 |
channel->set_is_servers_default(false); |
|
1769 |
|||
1770 |
48 |
args.GetReturnValue().Set(err); |
|
1771 |
} |
||
1772 |
|||
1773 |
7 |
void SetLocalAddress(const FunctionCallbackInfo<Value>& args) { |
|
1774 |
7 |
Environment* env = Environment::GetCurrent(args); |
|
1775 |
ChannelWrap* channel; |
||
1776 |
✗✓ | 10 |
ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder()); |
1777 |
|||
1778 |
✗✓ | 7 |
CHECK_EQ(args.Length(), 2); |
1779 |
✗✓ | 14 |
CHECK(args[0]->IsString()); |
1780 |
|||
1781 |
✓✗ | 7 |
Isolate* isolate = args.GetIsolate(); |
1782 |
7 |
node::Utf8Value ip0(isolate, args[0]); |
|
1783 |
|||
1784 |
unsigned char addr0[sizeof(struct in6_addr)]; |
||
1785 |
unsigned char addr1[sizeof(struct in6_addr)]; |
||
1786 |
7 |
int type0 = 0; |
|
1787 |
|||
1788 |
// This function accepts 2 arguments. The first may be either an IPv4 |
||
1789 |
// address or an IPv6 address. If present, the second argument must be the |
||
1790 |
// other type of address. Otherwise, the unspecified type of IP is set |
||
1791 |
// to 0 (any). |
||
1792 |
|||
1793 |
✓✓ | 7 |
if (uv_inet_pton(AF_INET, *ip0, &addr0) == 0) { |
1794 |
4 |
ares_set_local_ip4(channel->cares_channel(), ReadUint32BE(addr0)); |
|
1795 |
4 |
type0 = 4; |
|
1796 |
✓✓ | 3 |
} else if (uv_inet_pton(AF_INET6, *ip0, &addr0) == 0) { |
1797 |
2 |
ares_set_local_ip6(channel->cares_channel(), addr0); |
|
1798 |
2 |
type0 = 6; |
|
1799 |
} else { |
||
1800 |
1 |
THROW_ERR_INVALID_ARG_VALUE(env, "Invalid IP address."); |
|
1801 |
1 |
return; |
|
1802 |
} |
||
1803 |
|||
1804 |
✓✓ | 12 |
if (!args[1]->IsUndefined()) { |
1805 |
✗✓ | 8 |
CHECK(args[1]->IsString()); |
1806 |
4 |
node::Utf8Value ip1(isolate, args[1]); |
|
1807 |
|||
1808 |
✓✓ | 4 |
if (uv_inet_pton(AF_INET, *ip1, &addr1) == 0) { |
1809 |
✓✗ | 1 |
if (type0 == 4) { |
1810 |
1 |
THROW_ERR_INVALID_ARG_VALUE(env, "Cannot specify two IPv4 addresses."); |
|
1811 |
1 |
return; |
|
1812 |
} else { |
||
1813 |
ares_set_local_ip4(channel->cares_channel(), ReadUint32BE(addr1)); |
||
1814 |
} |
||
1815 |
✓✗ | 3 |
} else if (uv_inet_pton(AF_INET6, *ip1, &addr1) == 0) { |
1816 |
✓✓ | 3 |
if (type0 == 6) { |
1817 |
1 |
THROW_ERR_INVALID_ARG_VALUE(env, "Cannot specify two IPv6 addresses."); |
|
1818 |
1 |
return; |
|
1819 |
} else { |
||
1820 |
2 |
ares_set_local_ip6(channel->cares_channel(), addr1); |
|
1821 |
} |
||
1822 |
} else { |
||
1823 |
THROW_ERR_INVALID_ARG_VALUE(env, "Invalid IP address."); |
||
1824 |
return; |
||
1825 |
} |
||
1826 |
} else { |
||
1827 |
// No second arg specified |
||
1828 |
✓✓ | 2 |
if (type0 == 4) { |
1829 |
1 |
memset(&addr1, 0, sizeof(addr1)); |
|
1830 |
1 |
ares_set_local_ip6(channel->cares_channel(), addr1); |
|
1831 |
} else { |
||
1832 |
1 |
ares_set_local_ip4(channel->cares_channel(), 0); |
|
1833 |
} |
||
1834 |
} |
||
1835 |
} |
||
1836 |
|||
1837 |
6 |
void Cancel(const FunctionCallbackInfo<Value>& args) { |
|
1838 |
ChannelWrap* channel; |
||
1839 |
✗✓ | 6 |
ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder()); |
1840 |
|||
1841 |
✓✓✗✓ |
10 |
TRACE_EVENT_INSTANT0(TRACING_CATEGORY_NODE2(dns, native), |
1842 |
"cancel", TRACE_EVENT_SCOPE_THREAD); |
||
1843 |
|||
1844 |
6 |
ares_cancel(channel->cares_channel()); |
|
1845 |
} |
||
1846 |
|||
1847 |
const char EMSG_ESETSRVPENDING[] = "There are pending queries."; |
||
1848 |
1 |
void StrError(const FunctionCallbackInfo<Value>& args) { |
|
1849 |
1 |
Environment* env = Environment::GetCurrent(args); |
|
1850 |
1 |
int code = args[0]->Int32Value(env->context()).FromJust(); |
|
1851 |
✗✓ | 1 |
const char* errmsg = (code == DNS_ESETSRVPENDING) ? |
1852 |
EMSG_ESETSRVPENDING : |
||
1853 |
1 |
ares_strerror(code); |
|
1854 |
1 |
args.GetReturnValue().Set(OneByteString(env->isolate(), errmsg)); |
|
1855 |
1 |
} |
|
1856 |
|||
1857 |
} // namespace |
||
1858 |
|||
1859 |
2 |
inline void safe_free_hostent(struct hostent* host) { |
|
1860 |
int idx; |
||
1861 |
|||
1862 |
✓✗ | 2 |
if (host->h_addr_list != nullptr) { |
1863 |
2 |
idx = 0; |
|
1864 |
✓✓ | 4 |
while (host->h_addr_list[idx]) { |
1865 |
2 |
free(host->h_addr_list[idx++]); |
|
1866 |
} |
||
1867 |
2 |
free(host->h_addr_list); |
|
1868 |
2 |
host->h_addr_list = nullptr; |
|
1869 |
} |
||
1870 |
|||
1871 |
✓✗ | 2 |
if (host->h_aliases != nullptr) { |
1872 |
2 |
idx = 0; |
|
1873 |
✗✓ | 2 |
while (host->h_aliases[idx]) { |
1874 |
free(host->h_aliases[idx++]); |
||
1875 |
} |
||
1876 |
2 |
free(host->h_aliases); |
|
1877 |
2 |
host->h_aliases = nullptr; |
|
1878 |
} |
||
1879 |
|||
1880 |
2 |
free(host->h_name); |
|
1881 |
2 |
free(host); |
|
1882 |
2 |
} |
|
1883 |
|||
1884 |
1276 |
void Initialize(Local<Object> target, |
|
1885 |
Local<Value> unused, |
||
1886 |
Local<Context> context, |
||
1887 |
void* priv) { |
||
1888 |
1276 |
Environment* env = Environment::GetCurrent(context); |
|
1889 |
1276 |
Isolate* isolate = env->isolate(); |
|
1890 |
|||
1891 |
1276 |
SetMethod(context, target, "getaddrinfo", GetAddrInfo); |
|
1892 |
1276 |
SetMethod(context, target, "getnameinfo", GetNameInfo); |
|
1893 |
1276 |
SetMethodNoSideEffect(context, target, "canonicalizeIP", CanonicalizeIP); |
|
1894 |
|||
1895 |
1276 |
SetMethod(context, target, "strerror", StrError); |
|
1896 |
|||
1897 |
1276 |
target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET"), |
|
1898 |
5104 |
Integer::New(env->isolate(), AF_INET)).Check(); |
|
1899 |
1276 |
target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET6"), |
|
1900 |
5104 |
Integer::New(env->isolate(), AF_INET6)).Check(); |
|
1901 |
1276 |
target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), |
|
1902 |
"AF_UNSPEC"), |
||
1903 |
5104 |
Integer::New(env->isolate(), AF_UNSPEC)).Check(); |
|
1904 |
1276 |
target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), |
|
1905 |
"AI_ADDRCONFIG"), |
||
1906 |
5104 |
Integer::New(env->isolate(), AI_ADDRCONFIG)).Check(); |
|
1907 |
1276 |
target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), |
|
1908 |
"AI_ALL"), |
||
1909 |
5104 |
Integer::New(env->isolate(), AI_ALL)).Check(); |
|
1910 |
1276 |
target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), |
|
1911 |
"AI_V4MAPPED"), |
||
1912 |
3828 |
Integer::New(env->isolate(), AI_V4MAPPED)).Check(); |
|
1913 |
|||
1914 |
Local<FunctionTemplate> aiw = |
||
1915 |
1276 |
BaseObject::MakeLazilyInitializedJSTemplate(env); |
|
1916 |
1276 |
aiw->Inherit(AsyncWrap::GetConstructorTemplate(env)); |
|
1917 |
1276 |
SetConstructorFunction(context, target, "GetAddrInfoReqWrap", aiw); |
|
1918 |
|||
1919 |
Local<FunctionTemplate> niw = |
||
1920 |
1276 |
BaseObject::MakeLazilyInitializedJSTemplate(env); |
|
1921 |
1276 |
niw->Inherit(AsyncWrap::GetConstructorTemplate(env)); |
|
1922 |
1276 |
SetConstructorFunction(context, target, "GetNameInfoReqWrap", niw); |
|
1923 |
|||
1924 |
Local<FunctionTemplate> qrw = |
||
1925 |
1276 |
BaseObject::MakeLazilyInitializedJSTemplate(env); |
|
1926 |
1276 |
qrw->Inherit(AsyncWrap::GetConstructorTemplate(env)); |
|
1927 |
1276 |
SetConstructorFunction(context, target, "QueryReqWrap", qrw); |
|
1928 |
|||
1929 |
Local<FunctionTemplate> channel_wrap = |
||
1930 |
1276 |
NewFunctionTemplate(isolate, ChannelWrap::New); |
|
1931 |
2552 |
channel_wrap->InstanceTemplate()->SetInternalFieldCount( |
|
1932 |
ChannelWrap::kInternalFieldCount); |
||
1933 |
1276 |
channel_wrap->Inherit(AsyncWrap::GetConstructorTemplate(env)); |
|
1934 |
|||
1935 |
1276 |
SetProtoMethod(isolate, channel_wrap, "queryAny", Query<QueryAnyWrap>); |
|
1936 |
1276 |
SetProtoMethod(isolate, channel_wrap, "queryA", Query<QueryAWrap>); |
|
1937 |
1276 |
SetProtoMethod(isolate, channel_wrap, "queryAaaa", Query<QueryAaaaWrap>); |
|
1938 |
1276 |
SetProtoMethod(isolate, channel_wrap, "queryCaa", Query<QueryCaaWrap>); |
|
1939 |
1276 |
SetProtoMethod(isolate, channel_wrap, "queryCname", Query<QueryCnameWrap>); |
|
1940 |
1276 |
SetProtoMethod(isolate, channel_wrap, "queryMx", Query<QueryMxWrap>); |
|
1941 |
1276 |
SetProtoMethod(isolate, channel_wrap, "queryNs", Query<QueryNsWrap>); |
|
1942 |
1276 |
SetProtoMethod(isolate, channel_wrap, "queryTxt", Query<QueryTxtWrap>); |
|
1943 |
1276 |
SetProtoMethod(isolate, channel_wrap, "querySrv", Query<QuerySrvWrap>); |
|
1944 |
1276 |
SetProtoMethod(isolate, channel_wrap, "queryPtr", Query<QueryPtrWrap>); |
|
1945 |
1276 |
SetProtoMethod(isolate, channel_wrap, "queryNaptr", Query<QueryNaptrWrap>); |
|
1946 |
1276 |
SetProtoMethod(isolate, channel_wrap, "querySoa", Query<QuerySoaWrap>); |
|
1947 |
1276 |
SetProtoMethod( |
|
1948 |
isolate, channel_wrap, "getHostByAddr", Query<GetHostByAddrWrap>); |
||
1949 |
|||
1950 |
1276 |
SetProtoMethodNoSideEffect(isolate, channel_wrap, "getServers", GetServers); |
|
1951 |
1276 |
SetProtoMethod(isolate, channel_wrap, "setServers", SetServers); |
|
1952 |
1276 |
SetProtoMethod(isolate, channel_wrap, "setLocalAddress", SetLocalAddress); |
|
1953 |
1276 |
SetProtoMethod(isolate, channel_wrap, "cancel", Cancel); |
|
1954 |
|||
1955 |
1276 |
SetConstructorFunction(context, target, "ChannelWrap", channel_wrap); |
|
1956 |
1276 |
} |
|
1957 |
|||
1958 |
} // namespace cares_wrap |
||
1959 |
} // namespace node |
||
1960 |
|||
1961 |
5545 |
NODE_MODULE_CONTEXT_AWARE_INTERNAL(cares_wrap, node::cares_wrap::Initialize) |
Generated by: GCOVR (Version 4.2) |