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