File: | out/../src/memory_tracker-inl.h |
Warning: | line 286, column 3 Access to field 'size_' results in a dereference of a null pointer (loaded from variable 'n') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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_CAA257 | |||
42 | # define T_CAA257 257 /* Certification Authority Authorization */ | |||
43 | #endif | |||
44 | ||||
45 | // OpenBSD does not define these | |||
46 | #ifndef AI_ALL0x0010 | |||
47 | # define AI_ALL0x0010 0 | |||
48 | #endif | |||
49 | #ifndef AI_V4MAPPED0x0008 | |||
50 | # define AI_V4MAPPED0x0008 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 | inline uint16_t cares_get_16bit(const unsigned char* p) { | |||
80 | return static_cast<uint32_t>(p[0] << 8U) | (static_cast<uint32_t>(p[1])); | |||
81 | } | |||
82 | ||||
83 | void ares_poll_cb(uv_poll_t* watcher, int status, int events) { | |||
84 | NodeAresTask* task = ContainerOf(&NodeAresTask::poll_watcher, watcher); | |||
85 | ChannelWrap* channel = task->channel; | |||
86 | ||||
87 | /* Reset the idle timer */ | |||
88 | uv_timer_again(channel->timer_handle()); | |||
89 | ||||
90 | 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 | ares_process_fd(channel->cares_channel(), | |||
99 | events & UV_READABLE ? task->sock : ARES_SOCKET_BAD-1, | |||
100 | events & UV_WRITABLE ? task->sock : ARES_SOCKET_BAD-1); | |||
101 | } | |||
102 | ||||
103 | ||||
104 | void ares_poll_close_cb(uv_poll_t* watcher) { | |||
105 | std::unique_ptr<NodeAresTask> free_me( | |||
106 | ContainerOf(&NodeAresTask::poll_watcher, watcher)); | |||
107 | } | |||
108 | ||||
109 | ||||
110 | /* Callback from ares when socket operation is started */ | |||
111 | void ares_sockstate_cb(void* data, ares_socket_t sock, int read, int write) { | |||
112 | ChannelWrap* channel = static_cast<ChannelWrap*>(data); | |||
113 | NodeAresTask* task; | |||
114 | ||||
115 | NodeAresTask lookup_task; | |||
116 | lookup_task.sock = sock; | |||
117 | auto it = channel->task_list()->find(&lookup_task); | |||
118 | ||||
119 | task = (it == channel->task_list()->end()) ? nullptr : *it; | |||
120 | ||||
121 | if (read || write) { | |||
122 | if (!task) { | |||
123 | /* New socket */ | |||
124 | channel->StartTimer(); | |||
125 | ||||
126 | task = NodeAresTask::Create(channel, sock); | |||
127 | 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 | channel->task_list()->insert(task); | |||
135 | } | |||
136 | ||||
137 | /* This should never fail. If it fails anyway, the query will eventually */ | |||
138 | /* time out. */ | |||
139 | uv_poll_start(&task->poll_watcher, | |||
140 | (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 | CHECK(task &&do { if (__builtin_expect(!!(!(task && "When an ares socket is closed we should have a handle for it" )), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "148", "task && \"When an ares socket is closed we should have a handle for it\"" , __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0) | |||
148 | "When an ares socket is closed we should have a handle for it")do { if (__builtin_expect(!!(!(task && "When an ares socket is closed we should have a handle for it" )), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "148", "task && \"When an ares socket is closed we should have a handle for it\"" , __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
149 | ||||
150 | channel->task_list()->erase(it); | |||
151 | channel->env()->CloseHandle(&task->poll_watcher, ares_poll_close_cb); | |||
152 | ||||
153 | if (channel->task_list()->empty()) { | |||
154 | channel->CloseTimer(); | |||
155 | } | |||
156 | } | |||
157 | } | |||
158 | ||||
159 | Local<Array> HostentToNames(Environment* env, struct hostent* host) { | |||
160 | EscapableHandleScope scope(env->isolate()); | |||
161 | ||||
162 | std::vector<Local<Value>> names; | |||
163 | ||||
164 | for (uint32_t i = 0; host->h_aliases[i] != nullptr; ++i) | |||
165 | names.emplace_back(OneByteString(env->isolate(), host->h_aliases[i])); | |||
166 | ||||
167 | Local<Array> ret = Array::New(env->isolate(), names.data(), names.size()); | |||
168 | ||||
169 | return scope.Escape(ret); | |||
170 | } | |||
171 | ||||
172 | Local<Array> HostentToNames(Environment* env, | |||
173 | struct hostent* host, | |||
174 | Local<Array> names) { | |||
175 | size_t offset = names->Length(); | |||
176 | ||||
177 | for (uint32_t i = 0; host->h_aliases[i] != nullptr; ++i) { | |||
178 | names->Set( | |||
179 | env->context(), | |||
180 | i + offset, | |||
181 | OneByteString(env->isolate(), host->h_aliases[i])).Check(); | |||
182 | } | |||
183 | ||||
184 | return names; | |||
185 | } | |||
186 | ||||
187 | template <typename T> | |||
188 | Local<Array> AddrTTLToArray( | |||
189 | Environment* env, | |||
190 | const T* addrttls, | |||
191 | size_t naddrttls) { | |||
192 | MaybeStackBuffer<Local<Value>, 8> ttls(naddrttls); | |||
193 | for (size_t i = 0; i < naddrttls; i++) | |||
194 | ttls[i] = Integer::NewFromUnsigned(env->isolate(), addrttls[i].ttl); | |||
195 | ||||
196 | return Array::New(env->isolate(), ttls.out(), naddrttls); | |||
197 | } | |||
198 | ||||
199 | 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 | HandleScope handle_scope(env->isolate()); | |||
208 | hostent* host; | |||
209 | ||||
210 | int status; | |||
211 | switch (*type) { | |||
212 | case ns_t_a: | |||
213 | case ns_t_cname: | |||
214 | case ns_t_cname_or_a: | |||
215 | status = ares_parse_a_reply(buf, | |||
216 | len, | |||
217 | &host, | |||
218 | static_cast<ares_addrttl*>(addrttls), | |||
219 | naddrttls); | |||
220 | break; | |||
221 | case ns_t_aaaa: | |||
222 | status = ares_parse_aaaa_reply(buf, | |||
223 | len, | |||
224 | &host, | |||
225 | static_cast<ares_addr6ttl*>(addrttls), | |||
226 | naddrttls); | |||
227 | break; | |||
228 | case ns_t_ns: | |||
229 | status = ares_parse_ns_reply(buf, len, &host); | |||
230 | break; | |||
231 | case ns_t_ptr: | |||
232 | status = ares_parse_ptr_reply(buf, len, nullptr, 0, AF_INET2, &host); | |||
233 | break; | |||
234 | default: | |||
235 | CHECK(0 && "Bad NS type")do { if (__builtin_expect(!!(!(0 && "Bad NS type")), 0 )) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "235", "0 && \"Bad NS type\"", __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
236 | break; | |||
237 | } | |||
238 | ||||
239 | if (status != ARES_SUCCESS0) | |||
240 | return status; | |||
241 | ||||
242 | CHECK_NOT_NULL(host)do { if (__builtin_expect(!!(!((host) != nullptr)), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "242", "(host) != nullptr", __PRETTY_FUNCTION__ }; node:: Assert(args); } while (0); } } while (0); | |||
243 | 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 | if ((*type == ns_t_cname_or_a && ptr->h_name && ptr->h_aliases[0]) || | |||
249 | *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_SUCCESS0; | |||
257 | } | |||
258 | ||||
259 | if (*type == ns_t_cname_or_a) | |||
260 | *type = ns_t_a; | |||
261 | ||||
262 | if (*type == ns_t_ns) { | |||
263 | HostentToNames(env, ptr.get(), ret); | |||
264 | } else if (*type == ns_t_ptr) { | |||
265 | uint32_t offset = ret->Length(); | |||
266 | for (uint32_t i = 0; ptr->h_aliases[i] != nullptr; i++) { | |||
267 | auto alias = OneByteString(env->isolate(), ptr->h_aliases[i]); | |||
268 | ret->Set(env->context(), i + offset, alias).Check(); | |||
269 | } | |||
270 | } else { | |||
271 | uint32_t offset = ret->Length(); | |||
272 | char ip[INET6_ADDRSTRLEN46]; | |||
273 | for (uint32_t i = 0; ptr->h_addr_list[i] != nullptr; ++i) { | |||
274 | uv_inet_ntop(ptr->h_addrtype, ptr->h_addr_list[i], ip, sizeof(ip)); | |||
275 | auto address = OneByteString(env->isolate(), ip); | |||
276 | ret->Set(env->context(), i + offset, address).Check(); | |||
277 | } | |||
278 | } | |||
279 | ||||
280 | return ARES_SUCCESS0; | |||
281 | } | |||
282 | ||||
283 | int ParseMxReply( | |||
284 | Environment* env, | |||
285 | const unsigned char* buf, | |||
286 | int len, | |||
287 | Local<Array> ret, | |||
288 | bool need_type = false) { | |||
289 | HandleScope handle_scope(env->isolate()); | |||
290 | ||||
291 | struct ares_mx_reply* mx_start; | |||
292 | int status = ares_parse_mx_reply(buf, len, &mx_start); | |||
293 | if (status != ARES_SUCCESS0) | |||
294 | return status; | |||
295 | ||||
296 | uint32_t offset = ret->Length(); | |||
297 | ares_mx_reply* current = mx_start; | |||
298 | for (uint32_t i = 0; current != nullptr; ++i, current = current->next) { | |||
299 | Local<Object> mx_record = Object::New(env->isolate()); | |||
300 | mx_record->Set(env->context(), | |||
301 | env->exchange_string(), | |||
302 | OneByteString(env->isolate(), current->host)).Check(); | |||
303 | mx_record->Set(env->context(), | |||
304 | env->priority_string(), | |||
305 | Integer::New(env->isolate(), current->priority)).Check(); | |||
306 | if (need_type) | |||
307 | mx_record->Set(env->context(), | |||
308 | env->type_string(), | |||
309 | env->dns_mx_string()).Check(); | |||
310 | ||||
311 | ret->Set(env->context(), i + offset, mx_record).Check(); | |||
312 | } | |||
313 | ||||
314 | ares_free_data(mx_start); | |||
315 | return ARES_SUCCESS0; | |||
316 | } | |||
317 | ||||
318 | int ParseCaaReply( | |||
319 | Environment* env, | |||
320 | const unsigned char* buf, | |||
321 | int len, | |||
322 | Local<Array> ret, | |||
323 | bool need_type = false) { | |||
324 | HandleScope handle_scope(env->isolate()); | |||
325 | ||||
326 | struct ares_caa_reply* caa_start; | |||
327 | int status = ares_parse_caa_reply(buf, len, &caa_start); | |||
328 | if (status != ARES_SUCCESS0) | |||
329 | return status; | |||
330 | ||||
331 | uint32_t offset = ret->Length(); | |||
332 | ares_caa_reply* current = caa_start; | |||
333 | for (uint32_t i = 0; current != nullptr; ++i, current = current->next) { | |||
334 | Local<Object> caa_record = Object::New(env->isolate()); | |||
335 | ||||
336 | caa_record->Set(env->context(), | |||
337 | env->dns_critical_string(), | |||
338 | Integer::New(env->isolate(), current->critical)).Check(); | |||
339 | caa_record->Set(env->context(), | |||
340 | OneByteString(env->isolate(), current->property), | |||
341 | OneByteString(env->isolate(), current->value)).Check(); | |||
342 | if (need_type) | |||
343 | caa_record->Set(env->context(), | |||
344 | env->type_string(), | |||
345 | env->dns_caa_string()).Check(); | |||
346 | ||||
347 | ret->Set(env->context(), i + offset, caa_record).Check(); | |||
348 | } | |||
349 | ||||
350 | ares_free_data(caa_start); | |||
351 | return ARES_SUCCESS0; | |||
352 | } | |||
353 | ||||
354 | int ParseTxtReply( | |||
355 | Environment* env, | |||
356 | const unsigned char* buf, | |||
357 | int len, | |||
358 | Local<Array> ret, | |||
359 | bool need_type = false) { | |||
360 | HandleScope handle_scope(env->isolate()); | |||
361 | ||||
362 | struct ares_txt_ext* txt_out; | |||
363 | ||||
364 | int status = ares_parse_txt_reply_ext(buf, len, &txt_out); | |||
365 | if (status != ARES_SUCCESS0) | |||
366 | return status; | |||
367 | ||||
368 | Local<Array> txt_chunk; | |||
369 | ||||
370 | struct ares_txt_ext* current = txt_out; | |||
371 | uint32_t i = 0, j; | |||
372 | uint32_t offset = ret->Length(); | |||
373 | for (j = 0; current != nullptr; current = current->next) { | |||
374 | Local<String> txt = | |||
375 | OneByteString(env->isolate(), current->txt, current->length); | |||
376 | ||||
377 | // New record found - write out the current chunk | |||
378 | if (current->record_start) { | |||
379 | 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 | txt_chunk = Array::New(env->isolate()); | |||
393 | j = 0; | |||
394 | } | |||
395 | ||||
396 | txt_chunk->Set(env->context(), j++, txt).Check(); | |||
397 | } | |||
398 | ||||
399 | // Push last chunk if it isn't empty | |||
400 | if (!txt_chunk.IsEmpty()) { | |||
401 | if (need_type) { | |||
402 | Local<Object> elem = Object::New(env->isolate()); | |||
403 | elem->Set(env->context(), env->entries_string(), txt_chunk).Check(); | |||
404 | elem->Set(env->context(), | |||
405 | env->type_string(), | |||
406 | env->dns_txt_string()).Check(); | |||
407 | ret->Set(env->context(), offset + i, elem).Check(); | |||
408 | } else { | |||
409 | ret->Set(env->context(), offset + i, txt_chunk).Check(); | |||
410 | } | |||
411 | } | |||
412 | ||||
413 | ares_free_data(txt_out); | |||
414 | return ARES_SUCCESS0; | |||
415 | } | |||
416 | ||||
417 | ||||
418 | int ParseSrvReply( | |||
419 | Environment* env, | |||
420 | const unsigned char* buf, | |||
421 | int len, | |||
422 | Local<Array> ret, | |||
423 | bool need_type = false) { | |||
424 | HandleScope handle_scope(env->isolate()); | |||
425 | ||||
426 | struct ares_srv_reply* srv_start; | |||
427 | int status = ares_parse_srv_reply(buf, len, &srv_start); | |||
428 | if (status != ARES_SUCCESS0) | |||
429 | return status; | |||
430 | ||||
431 | ares_srv_reply* current = srv_start; | |||
432 | int offset = ret->Length(); | |||
433 | 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 | ares_free_data(srv_start); | |||
456 | return ARES_SUCCESS0; | |||
457 | } | |||
458 | ||||
459 | ||||
460 | int ParseNaptrReply( | |||
461 | Environment* env, | |||
462 | const unsigned char* buf, | |||
463 | int len, | |||
464 | Local<Array> ret, | |||
465 | bool need_type = false) { | |||
466 | HandleScope handle_scope(env->isolate()); | |||
467 | ||||
468 | ares_naptr_reply* naptr_start; | |||
469 | int status = ares_parse_naptr_reply(buf, len, &naptr_start); | |||
470 | ||||
471 | if (status != ARES_SUCCESS0) | |||
472 | return status; | |||
473 | ||||
474 | ares_naptr_reply* current = naptr_start; | |||
475 | int offset = ret->Length(); | |||
476 | 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 | ares_free_data(naptr_start); | |||
509 | return ARES_SUCCESS0; | |||
510 | } | |||
511 | ||||
512 | ||||
513 | int ParseSoaReply( | |||
514 | Environment* env, | |||
515 | unsigned char* buf, | |||
516 | int len, | |||
517 | Local<Object>* ret) { | |||
518 | EscapableHandleScope handle_scope(env->isolate()); | |||
519 | ||||
520 | // Manage memory using standardard smart pointer std::unique_tr | |||
521 | struct AresDeleter { | |||
522 | 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 | const unsigned int ancount = cares_get_16bit(buf + 6); | |||
528 | unsigned char* ptr = buf + NS_HFIXEDSZ12; | |||
529 | char* name_temp = nullptr; | |||
530 | long temp_len; // NOLINT(runtime/int) | |||
531 | int status = ares_expand_name(ptr, buf, len, &name_temp, &temp_len); | |||
532 | if (status != ARES_SUCCESS0) { | |||
533 | // returns EBADRESP in case of invalid input | |||
534 | return status == ARES_EBADNAME8 ? ARES_EBADRESP10 : status; | |||
535 | } | |||
536 | ||||
537 | const ares_unique_ptr name(name_temp); | |||
538 | ||||
539 | if (ptr + temp_len + NS_QFIXEDSZ4 > buf + len) { | |||
540 | return ARES_EBADRESP10; | |||
541 | } | |||
542 | ptr += temp_len + NS_QFIXEDSZ4; | |||
543 | ||||
544 | for (unsigned int i = 0; i < ancount; i++) { | |||
545 | char* rr_name_temp = nullptr; | |||
546 | long rr_temp_len; // NOLINT(runtime/int) | |||
547 | int status2 = ares_expand_name(ptr, buf, len, &rr_name_temp, &rr_temp_len); | |||
548 | ||||
549 | if (status2 != ARES_SUCCESS0) | |||
550 | return status2 == ARES_EBADNAME8 ? ARES_EBADRESP10 : status2; | |||
551 | ||||
552 | const ares_unique_ptr rr_name(rr_name_temp); | |||
553 | ||||
554 | ptr += rr_temp_len; | |||
555 | if (ptr + NS_RRFIXEDSZ10 > buf + len) { | |||
556 | return ARES_EBADRESP10; | |||
557 | } | |||
558 | ||||
559 | const int rr_type = cares_get_16bit(ptr); | |||
560 | const int rr_len = cares_get_16bit(ptr + 8); | |||
561 | ptr += NS_RRFIXEDSZ10; | |||
562 | ||||
563 | // only need SOA | |||
564 | if (rr_type == ns_t_soa) { | |||
565 | char* nsname_temp = nullptr; | |||
566 | long nsname_temp_len; // NOLINT(runtime/int) | |||
567 | ||||
568 | int status3 = ares_expand_name(ptr, buf, len, | |||
569 | &nsname_temp, | |||
570 | &nsname_temp_len); | |||
571 | if (status3 != ARES_SUCCESS0) { | |||
572 | return status3 == ARES_EBADNAME8 ? ARES_EBADRESP10 : status3; | |||
573 | } | |||
574 | const ares_unique_ptr nsname(nsname_temp); | |||
575 | ptr += nsname_temp_len; | |||
576 | ||||
577 | char* hostmaster_temp = nullptr; | |||
578 | long hostmaster_temp_len; // NOLINT(runtime/int) | |||
579 | int status4 = ares_expand_name(ptr, buf, len, | |||
580 | &hostmaster_temp, | |||
581 | &hostmaster_temp_len); | |||
582 | if (status4 != ARES_SUCCESS0) { | |||
583 | return status4 == ARES_EBADNAME8 ? ARES_EBADRESP10 : status4; | |||
584 | } | |||
585 | const ares_unique_ptr hostmaster(hostmaster_temp); | |||
586 | ptr += hostmaster_temp_len; | |||
587 | ||||
588 | if (ptr + 5 * 4 > buf + len) { | |||
589 | return ARES_EBADRESP10; | |||
590 | } | |||
591 | ||||
592 | const unsigned int serial = ReadUint32BE(ptr + 0 * 4); | |||
593 | const unsigned int refresh = ReadUint32BE(ptr + 1 * 4); | |||
594 | const unsigned int retry = ReadUint32BE(ptr + 2 * 4); | |||
595 | const unsigned int expire = ReadUint32BE(ptr + 3 * 4); | |||
596 | const unsigned int minttl = ReadUint32BE(ptr + 4 * 4); | |||
597 | ||||
598 | Local<Object> soa_record = Object::New(env->isolate()); | |||
599 | soa_record->Set(env->context(), | |||
600 | env->nsname_string(), | |||
601 | OneByteString(env->isolate(), nsname.get())).Check(); | |||
602 | soa_record->Set(env->context(), | |||
603 | env->hostmaster_string(), | |||
604 | OneByteString(env->isolate(), | |||
605 | hostmaster.get())).Check(); | |||
606 | soa_record->Set(env->context(), | |||
607 | env->serial_string(), | |||
608 | Integer::NewFromUnsigned(env->isolate(), serial)).Check(); | |||
609 | soa_record->Set(env->context(), | |||
610 | env->refresh_string(), | |||
611 | Integer::New(env->isolate(), refresh)).Check(); | |||
612 | soa_record->Set(env->context(), | |||
613 | env->retry_string(), | |||
614 | Integer::New(env->isolate(), retry)).Check(); | |||
615 | soa_record->Set(env->context(), | |||
616 | env->expire_string(), | |||
617 | Integer::New(env->isolate(), expire)).Check(); | |||
618 | soa_record->Set(env->context(), | |||
619 | env->minttl_string(), | |||
620 | Integer::NewFromUnsigned(env->isolate(), minttl)).Check(); | |||
621 | soa_record->Set(env->context(), | |||
622 | env->type_string(), | |||
623 | env->dns_soa_string()).Check(); | |||
624 | ||||
625 | ||||
626 | *ret = handle_scope.Escape(soa_record); | |||
627 | break; | |||
628 | } | |||
629 | ||||
630 | ptr += rr_len; | |||
631 | } | |||
632 | ||||
633 | return ARES_SUCCESS0; | |||
634 | } | |||
635 | } // anonymous namespace | |||
636 | ||||
637 | ChannelWrap::ChannelWrap( | |||
638 | Environment* env, | |||
639 | Local<Object> object, | |||
640 | int timeout, | |||
641 | int tries) | |||
642 | : AsyncWrap(env, object, PROVIDER_DNSCHANNEL), | |||
643 | timeout_(timeout), | |||
644 | tries_(tries) { | |||
645 | MakeWeak(); | |||
646 | ||||
647 | Setup(); | |||
648 | } | |||
649 | ||||
650 | void ChannelWrap::MemoryInfo(MemoryTracker* tracker) const { | |||
651 | if (timer_handle_ != nullptr) | |||
652 | tracker->TrackField("timer_handle", *timer_handle_); | |||
653 | tracker->TrackField("task_list", task_list_, "NodeAresTask::List"); | |||
654 | } | |||
655 | ||||
656 | void ChannelWrap::New(const FunctionCallbackInfo<Value>& args) { | |||
657 | CHECK(args.IsConstructCall())do { if (__builtin_expect(!!(!(args.IsConstructCall())), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "657", "args.IsConstructCall()", __PRETTY_FUNCTION__ }; node ::Assert(args); } while (0); } } while (0); | |||
658 | CHECK_EQ(args.Length(), 2)do { if (__builtin_expect(!!(!((args.Length()) == (2))), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "658", "(args.Length()) == (2)", __PRETTY_FUNCTION__ }; node ::Assert(args); } while (0); } } while (0); | |||
659 | CHECK(args[0]->IsInt32())do { if (__builtin_expect(!!(!(args[0]->IsInt32())), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "659", "args[0]->IsInt32()", __PRETTY_FUNCTION__ }; node ::Assert(args); } while (0); } } while (0); | |||
660 | CHECK(args[1]->IsInt32())do { if (__builtin_expect(!!(!(args[1]->IsInt32())), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "660", "args[1]->IsInt32()", __PRETTY_FUNCTION__ }; node ::Assert(args); } while (0); } } while (0); | |||
661 | const int timeout = args[0].As<Int32>()->Value(); | |||
662 | const int tries = args[1].As<Int32>()->Value(); | |||
663 | Environment* env = Environment::GetCurrent(args); | |||
664 | new ChannelWrap(env, args.This(), timeout, tries); | |||
665 | } | |||
666 | ||||
667 | GetAddrInfoReqWrap::GetAddrInfoReqWrap( | |||
668 | Environment* env, | |||
669 | Local<Object> req_wrap_obj, | |||
670 | bool verbatim) | |||
671 | : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETADDRINFOREQWRAP), | |||
672 | verbatim_(verbatim) {} | |||
673 | ||||
674 | GetNameInfoReqWrap::GetNameInfoReqWrap( | |||
675 | Environment* env, | |||
676 | Local<Object> req_wrap_obj) | |||
677 | : 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 | void ChannelWrap::AresTimeout(uv_timer_t* handle) { | |||
682 | ChannelWrap* channel = static_cast<ChannelWrap*>(handle->data); | |||
683 | CHECK_EQ(channel->timer_handle(), handle)do { if (__builtin_expect(!!(!((channel->timer_handle()) == (handle))), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "683", "(channel->timer_handle()) == (handle)" , __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
684 | CHECK_EQ(false, channel->task_list()->empty())do { if (__builtin_expect(!!(!((false) == (channel->task_list ()->empty()))), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "684", "(false) == (channel->task_list()->empty())" , __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
685 | ares_process_fd(channel->cares_channel(), ARES_SOCKET_BAD-1, ARES_SOCKET_BAD-1); | |||
686 | } | |||
687 | ||||
688 | ||||
689 | void NodeAresTask::MemoryInfo(MemoryTracker* tracker) const { | |||
690 | tracker->TrackField("channel", channel); | |||
| ||||
691 | } | |||
692 | ||||
693 | /* Allocates and returns a new NodeAresTask */ | |||
694 | NodeAresTask* NodeAresTask::Create(ChannelWrap* channel, ares_socket_t sock) { | |||
695 | auto task = new NodeAresTask(); | |||
696 | ||||
697 | task->channel = channel; | |||
698 | task->sock = sock; | |||
699 | ||||
700 | if (uv_poll_init_socket(channel->env()->event_loop(), | |||
701 | &task->poll_watcher, sock) < 0) { | |||
702 | /* This should never happen. */ | |||
703 | delete task; | |||
704 | return nullptr; | |||
705 | } | |||
706 | ||||
707 | return task; | |||
708 | } | |||
709 | ||||
710 | void ChannelWrap::Setup() { | |||
711 | struct ares_options options; | |||
712 | memset(&options, 0, sizeof(options)); | |||
713 | options.flags = ARES_FLAG_NOCHECKRESP(1 << 7); | |||
714 | options.sock_state_cb = ares_sockstate_cb; | |||
715 | options.sock_state_cb_data = this; | |||
716 | options.timeout = timeout_; | |||
717 | options.tries = tries_; | |||
718 | ||||
719 | int r; | |||
720 | if (!library_inited_) { | |||
721 | 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 | r = ares_library_init(ARES_LIB_INIT_ALL((1 << 0))); | |||
725 | if (r != ARES_SUCCESS0) | |||
726 | return env()->ThrowError(ToErrorCodeString(r)); | |||
727 | } | |||
728 | ||||
729 | /* We do the call to ares_init_option for caller. */ | |||
730 | const int optmask = | |||
731 | ARES_OPT_FLAGS(1 << 0) | ARES_OPT_TIMEOUTMS(1 << 13) | | |||
732 | ARES_OPT_SOCK_STATE_CB(1 << 9) | ARES_OPT_TRIES(1 << 2); | |||
733 | r = ares_init_options(&channel_, &options, optmask); | |||
734 | ||||
735 | if (r != ARES_SUCCESS0) { | |||
736 | Mutex::ScopedLock lock(ares_library_mutex); | |||
737 | ares_library_cleanup(); | |||
738 | return env()->ThrowError(ToErrorCodeString(r)); | |||
739 | } | |||
740 | ||||
741 | library_inited_ = true; | |||
742 | } | |||
743 | ||||
744 | void ChannelWrap::StartTimer() { | |||
745 | if (timer_handle_ == nullptr) { | |||
746 | timer_handle_ = new uv_timer_t(); | |||
747 | timer_handle_->data = static_cast<void*>(this); | |||
748 | 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 | int timeout = timeout_; | |||
753 | if (timeout == 0) timeout = 1; | |||
754 | if (timeout < 0 || timeout > 1000) timeout = 1000; | |||
755 | uv_timer_start(timer_handle_, AresTimeout, timeout, timeout); | |||
756 | } | |||
757 | ||||
758 | void ChannelWrap::CloseTimer() { | |||
759 | if (timer_handle_ == nullptr) | |||
760 | return; | |||
761 | ||||
762 | env()->CloseHandle(timer_handle_, [](uv_timer_t* handle) { delete handle; }); | |||
763 | timer_handle_ = nullptr; | |||
764 | } | |||
765 | ||||
766 | ChannelWrap::~ChannelWrap() { | |||
767 | ares_destroy(channel_); | |||
768 | ||||
769 | if (library_inited_) { | |||
770 | Mutex::ScopedLock lock(ares_library_mutex); | |||
771 | // This decreases the reference counter increased by ares_library_init(). | |||
772 | ares_library_cleanup(); | |||
773 | } | |||
774 | ||||
775 | CloseTimer(); | |||
776 | } | |||
777 | ||||
778 | ||||
779 | void ChannelWrap::ModifyActivityQueryCount(int count) { | |||
780 | active_query_count_ += count; | |||
781 | CHECK_GE(active_query_count_, 0)do { if (__builtin_expect(!!(!((active_query_count_) >= (0 ))), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "781", "(active_query_count_) >= (0)", __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
782 | } | |||
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 | void ChannelWrap::EnsureServers() { | |||
793 | /* if last query is OK or servers are set by user self, do not check */ | |||
794 | if (query_last_ok_ || !is_servers_default_) { | |||
795 | 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_INET2 || | |||
812 | servers[0].addr.addr4.s_addr != htonl(INADDR_LOOPBACK)__bswap_32 (((in_addr_t) 0x7f000001)) || | |||
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 | int AnyTraits::Send(QueryWrap<AnyTraits>* wrap, const char* name) { | |||
831 | wrap->AresQuery(name, ns_c_in, ns_t_any); | |||
832 | return 0; | |||
833 | } | |||
834 | ||||
835 | int ATraits::Send(QueryWrap<ATraits>* wrap, const char* name) { | |||
836 | wrap->AresQuery(name, ns_c_in, ns_t_a); | |||
837 | return 0; | |||
838 | } | |||
839 | ||||
840 | int AaaaTraits::Send(QueryWrap<AaaaTraits>* wrap, const char* name) { | |||
841 | wrap->AresQuery(name, ns_c_in, ns_t_aaaa); | |||
842 | return 0; | |||
843 | } | |||
844 | ||||
845 | int CaaTraits::Send(QueryWrap<CaaTraits>* wrap, const char* name) { | |||
846 | wrap->AresQuery(name, ns_c_in, T_CAA257); | |||
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 | int MxTraits::Send(QueryWrap<MxTraits>* wrap, const char* name) { | |||
856 | wrap->AresQuery(name, ns_c_in, ns_t_mx); | |||
857 | 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 | int SoaTraits::Send(QueryWrap<SoaTraits>* wrap, const char* name) { | |||
886 | wrap->AresQuery(name, ns_c_in, ns_t_soa); | |||
887 | return 0; | |||
888 | } | |||
889 | ||||
890 | int AnyTraits::Parse( | |||
891 | QueryAnyWrap* wrap, | |||
892 | const std::unique_ptr<ResponseData>& response) { | |||
893 | if (UNLIKELY(response->is_host)__builtin_expect(!!(response->is_host), 0)) | |||
894 | return ARES_EBADRESP10; | |||
895 | ||||
896 | unsigned char* buf = response->buf.data; | |||
897 | int len = response->buf.size; | |||
898 | ||||
899 | Environment* env = wrap->env(); | |||
900 | HandleScope handle_scope(env->isolate()); | |||
901 | Context::Scope context_scope(env->context()); | |||
902 | ||||
903 | 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 | int naddrttls = arraysize(addrttls); | |||
909 | ||||
910 | type = ns_t_cname_or_a; | |||
911 | status = ParseGeneralReply(env, | |||
912 | buf, | |||
913 | len, | |||
914 | &type, | |||
915 | ret, | |||
916 | addrttls, | |||
917 | &naddrttls); | |||
918 | uint32_t a_count = ret->Length(); | |||
919 | if (status != ARES_SUCCESS0 && status != ARES_ENODATA1) | |||
920 | return status; | |||
921 | ||||
922 | if (type == ns_t_a) { | |||
923 | CHECK_EQ(static_cast<uint32_t>(naddrttls), a_count)do { if (__builtin_expect(!!(!((static_cast<uint32_t>(naddrttls )) == (a_count))), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "923", "(static_cast<uint32_t>(naddrttls)) == (a_count)" , __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
924 | for (uint32_t i = 0; i < a_count; i++) { | |||
925 | Local<Object> obj = Object::New(env->isolate()); | |||
926 | obj->Set(env->context(), | |||
927 | env->address_string(), | |||
928 | ret->Get(env->context(), i).ToLocalChecked()).Check(); | |||
929 | obj->Set(env->context(), | |||
930 | env->ttl_string(), | |||
931 | Integer::NewFromUnsigned( | |||
932 | env->isolate(), addrttls[i].ttl)).Check(); | |||
933 | obj->Set(env->context(), | |||
934 | env->type_string(), | |||
935 | env->dns_a_string()).Check(); | |||
936 | 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 | int naddr6ttls = arraysize(addr6ttls); | |||
954 | ||||
955 | type = ns_t_aaaa; | |||
956 | status = ParseGeneralReply(env, | |||
957 | buf, | |||
958 | len, | |||
959 | &type, | |||
960 | ret, | |||
961 | addr6ttls, | |||
962 | &naddr6ttls); | |||
963 | uint32_t aaaa_count = ret->Length() - a_count; | |||
964 | if (status != ARES_SUCCESS0 && status != ARES_ENODATA1) | |||
965 | return status; | |||
966 | ||||
967 | CHECK_EQ(aaaa_count, static_cast<uint32_t>(naddr6ttls))do { if (__builtin_expect(!!(!((aaaa_count) == (static_cast< uint32_t>(naddr6ttls)))), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "967", "(aaaa_count) == (static_cast<uint32_t>(naddr6ttls))" , __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
968 | CHECK_EQ(ret->Length(), a_count + aaaa_count)do { if (__builtin_expect(!!(!((ret->Length()) == (a_count + aaaa_count))), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "968", "(ret->Length()) == (a_count + aaaa_count)" , __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
969 | for (uint32_t i = a_count; i < ret->Length(); i++) { | |||
970 | Local<Object> obj = Object::New(env->isolate()); | |||
971 | obj->Set(env->context(), | |||
972 | env->address_string(), | |||
973 | ret->Get(env->context(), i).ToLocalChecked()).Check(); | |||
974 | obj->Set(env->context(), | |||
975 | env->ttl_string(), | |||
976 | Integer::NewFromUnsigned( | |||
977 | env->isolate(), addr6ttls[i - a_count].ttl)).Check(); | |||
978 | obj->Set(env->context(), | |||
979 | env->type_string(), | |||
980 | env->dns_aaaa_string()).Check(); | |||
981 | ret->Set(env->context(), i, obj).Check(); | |||
982 | } | |||
983 | ||||
984 | /* Parse MX records */ | |||
985 | status = ParseMxReply(env, buf, len, ret, true); | |||
986 | if (status != ARES_SUCCESS0 && status != ARES_ENODATA1) | |||
987 | return status; | |||
988 | ||||
989 | /* Parse NS records */ | |||
990 | type = ns_t_ns; | |||
991 | old_count = ret->Length(); | |||
992 | status = ParseGeneralReply(env, buf, len, &type, ret); | |||
993 | if (status != ARES_SUCCESS0 && status != ARES_ENODATA1) | |||
994 | return status; | |||
995 | ||||
996 | for (uint32_t i = old_count; i < ret->Length(); i++) { | |||
997 | Local<Object> obj = Object::New(env->isolate()); | |||
998 | obj->Set(env->context(), | |||
999 | env->value_string(), | |||
1000 | ret->Get(env->context(), i).ToLocalChecked()).Check(); | |||
1001 | obj->Set(env->context(), | |||
1002 | env->type_string(), | |||
1003 | env->dns_ns_string()).Check(); | |||
1004 | ret->Set(env->context(), i, obj).Check(); | |||
1005 | } | |||
1006 | ||||
1007 | /* Parse TXT records */ | |||
1008 | status = ParseTxtReply(env, buf, len, ret, true); | |||
1009 | if (status != ARES_SUCCESS0 && status != ARES_ENODATA1) | |||
1010 | return status; | |||
1011 | ||||
1012 | /* Parse SRV records */ | |||
1013 | status = ParseSrvReply(env, buf, len, ret, true); | |||
1014 | if (status != ARES_SUCCESS0 && status != ARES_ENODATA1) | |||
1015 | return status; | |||
1016 | ||||
1017 | /* Parse PTR records */ | |||
1018 | type = ns_t_ptr; | |||
1019 | old_count = ret->Length(); | |||
1020 | status = ParseGeneralReply(env, buf, len, &type, ret); | |||
1021 | if (status != ARES_SUCCESS0 && status != ARES_ENODATA1) | |||
1022 | return status; | |||
1023 | for (uint32_t i = old_count; i < ret->Length(); i++) { | |||
1024 | Local<Object> obj = Object::New(env->isolate()); | |||
1025 | obj->Set(env->context(), | |||
1026 | env->value_string(), | |||
1027 | ret->Get(env->context(), i).ToLocalChecked()).Check(); | |||
1028 | obj->Set(env->context(), | |||
1029 | env->type_string(), | |||
1030 | env->dns_ptr_string()).Check(); | |||
1031 | ret->Set(env->context(), i, obj).Check(); | |||
1032 | } | |||
1033 | ||||
1034 | /* Parse NAPTR records */ | |||
1035 | status = ParseNaptrReply(env, buf, len, ret, true); | |||
1036 | if (status != ARES_SUCCESS0 && status != ARES_ENODATA1) | |||
1037 | return status; | |||
1038 | ||||
1039 | /* Parse SOA records */ | |||
1040 | Local<Object> soa_record = Local<Object>(); | |||
1041 | status = ParseSoaReply(env, buf, len, &soa_record); | |||
1042 | if (status != ARES_SUCCESS0 && status != ARES_ENODATA1) | |||
1043 | return status; | |||
1044 | ||||
1045 | if (!soa_record.IsEmpty()) | |||
1046 | ret->Set(env->context(), ret->Length(), soa_record).Check(); | |||
1047 | ||||
1048 | /* Parse CAA records */ | |||
1049 | status = ParseCaaReply(env, buf, len, ret, true); | |||
1050 | if (status != ARES_SUCCESS0 && status != ARES_ENODATA1) | |||
1051 | return status; | |||
1052 | ||||
1053 | wrap->CallOnComplete(ret); | |||
1054 | return 0; | |||
1055 | } | |||
1056 | ||||
1057 | int ATraits::Parse( | |||
1058 | QueryAWrap* wrap, | |||
1059 | const std::unique_ptr<ResponseData>& response) { | |||
1060 | if (UNLIKELY(response->is_host)__builtin_expect(!!(response->is_host), 0)) | |||
1061 | return ARES_EBADRESP10; | |||
1062 | ||||
1063 | unsigned char* buf = response->buf.data; | |||
1064 | int len = response->buf.size; | |||
1065 | ||||
1066 | Environment* env = wrap->env(); | |||
1067 | HandleScope handle_scope(env->isolate()); | |||
1068 | Context::Scope context_scope(env->context()); | |||
1069 | ||||
1070 | ares_addrttl addrttls[256]; | |||
1071 | int naddrttls = arraysize(addrttls), status; | |||
1072 | Local<Array> ret = Array::New(env->isolate()); | |||
1073 | ||||
1074 | int type = ns_t_a; | |||
1075 | status = ParseGeneralReply(env, | |||
1076 | buf, | |||
1077 | len, | |||
1078 | &type, | |||
1079 | ret, | |||
1080 | addrttls, | |||
1081 | &naddrttls); | |||
1082 | if (status != ARES_SUCCESS0) | |||
1083 | return status; | |||
1084 | ||||
1085 | Local<Array> ttls = AddrTTLToArray<ares_addrttl>(env, addrttls, naddrttls); | |||
1086 | ||||
1087 | wrap->CallOnComplete(ret, ttls); | |||
1088 | return 0; | |||
1089 | } | |||
1090 | ||||
1091 | int AaaaTraits::Parse( | |||
1092 | QueryAaaaWrap* wrap, | |||
1093 | const std::unique_ptr<ResponseData>& response) { | |||
1094 | if (UNLIKELY(response->is_host)__builtin_expect(!!(response->is_host), 0)) | |||
1095 | return ARES_EBADRESP10; | |||
1096 | ||||
1097 | unsigned char* buf = response->buf.data; | |||
1098 | int len = response->buf.size; | |||
1099 | ||||
1100 | Environment* env = wrap->env(); | |||
1101 | HandleScope handle_scope(env->isolate()); | |||
1102 | Context::Scope context_scope(env->context()); | |||
1103 | ||||
1104 | ares_addr6ttl addrttls[256]; | |||
1105 | int naddrttls = arraysize(addrttls), status; | |||
1106 | Local<Array> ret = Array::New(env->isolate()); | |||
1107 | ||||
1108 | int type = ns_t_aaaa; | |||
1109 | status = ParseGeneralReply(env, | |||
1110 | buf, | |||
1111 | len, | |||
1112 | &type, | |||
1113 | ret, | |||
1114 | addrttls, | |||
1115 | &naddrttls); | |||
1116 | if (status != ARES_SUCCESS0) | |||
1117 | return status; | |||
1118 | ||||
1119 | Local<Array> ttls = AddrTTLToArray<ares_addr6ttl>(env, addrttls, naddrttls); | |||
1120 | ||||
1121 | wrap->CallOnComplete(ret, ttls); | |||
1122 | return 0; | |||
1123 | } | |||
1124 | ||||
1125 | int CaaTraits::Parse( | |||
1126 | QueryCaaWrap* wrap, | |||
1127 | const std::unique_ptr<ResponseData>& response) { | |||
1128 | if (UNLIKELY(response->is_host)__builtin_expect(!!(response->is_host), 0)) | |||
1129 | return ARES_EBADRESP10; | |||
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_SUCCESS0) | |||
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)__builtin_expect(!!(response->is_host), 0)) | |||
1151 | return ARES_EBADRESP10; | |||
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_SUCCESS0) | |||
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)__builtin_expect(!!(response->is_host), 0)) | |||
1174 | return ARES_EBADRESP10; | |||
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_SUCCESS0) | |||
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)__builtin_expect(!!(response->is_host), 0)) | |||
1197 | return ARES_EBADRESP10; | |||
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_SUCCESS0) | |||
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)__builtin_expect(!!(response->is_host), 0)) | |||
1220 | return ARES_EBADRESP10; | |||
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_SUCCESS0) | |||
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)__builtin_expect(!!(response->is_host), 0)) | |||
1242 | return ARES_EBADRESP10; | |||
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_SUCCESS0) | |||
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)__builtin_expect(!!(response->is_host), 0)) | |||
1264 | return ARES_EBADRESP10; | |||
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_SUCCESS0) | |||
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)__builtin_expect(!!(response->is_host), 0)) | |||
1288 | return ARES_EBADRESP10; | |||
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_SUCCESS0) | |||
1300 | return status; | |||
1301 | ||||
1302 | wrap->CallOnComplete(naptr_records); | |||
1303 | return 0; | |||
1304 | } | |||
1305 | ||||
1306 | int SoaTraits::Parse( | |||
1307 | QuerySoaWrap* wrap, | |||
1308 | const std::unique_ptr<ResponseData>& response) { | |||
1309 | if (UNLIKELY(response->is_host)__builtin_expect(!!(response->is_host), 0)) | |||
1310 | return ARES_EBADRESP10; | |||
1311 | ||||
1312 | unsigned char* buf = response->buf.data; | |||
1313 | int len = response->buf.size; | |||
1314 | ||||
1315 | Environment* env = wrap->env(); | |||
1316 | HandleScope handle_scope(env->isolate()); | |||
1317 | Context::Scope context_scope(env->context()); | |||
1318 | ||||
1319 | ares_soa_reply* soa_out; | |||
1320 | int status = ares_parse_soa_reply(buf, len, &soa_out); | |||
1321 | ||||
1322 | if (status != ARES_SUCCESS0) | |||
1323 | return status; | |||
1324 | ||||
1325 | Local<Object> soa_record = Object::New(env->isolate()); | |||
1326 | ||||
1327 | soa_record->Set(env->context(), | |||
1328 | env->nsname_string(), | |||
1329 | OneByteString(env->isolate(), soa_out->nsname)).Check(); | |||
1330 | soa_record->Set(env->context(), | |||
1331 | env->hostmaster_string(), | |||
1332 | OneByteString(env->isolate(), soa_out->hostmaster)).Check(); | |||
1333 | soa_record->Set(env->context(), | |||
1334 | env->serial_string(), | |||
1335 | Integer::NewFromUnsigned( | |||
1336 | env->isolate(), soa_out->serial)).Check(); | |||
1337 | soa_record->Set(env->context(), | |||
1338 | env->refresh_string(), | |||
1339 | Integer::New(env->isolate(), soa_out->refresh)).Check(); | |||
1340 | soa_record->Set(env->context(), | |||
1341 | env->retry_string(), | |||
1342 | Integer::New(env->isolate(), soa_out->retry)).Check(); | |||
1343 | soa_record->Set(env->context(), | |||
1344 | env->expire_string(), | |||
1345 | Integer::New(env->isolate(), soa_out->expire)).Check(); | |||
1346 | soa_record->Set(env->context(), | |||
1347 | env->minttl_string(), | |||
1348 | Integer::NewFromUnsigned( | |||
1349 | env->isolate(), soa_out->minttl)).Check(); | |||
1350 | ||||
1351 | ares_free_data(soa_out); | |||
1352 | ||||
1353 | wrap->CallOnComplete(soa_record); | |||
1354 | return 0; | |||
1355 | } | |||
1356 | ||||
1357 | int ReverseTraits::Send(GetHostByAddrWrap* wrap, const char* name) { | |||
1358 | int length, family; | |||
1359 | char address_buffer[sizeof(struct in6_addr)]; | |||
1360 | ||||
1361 | if (uv_inet_pton(AF_INET2, name, &address_buffer) == 0) { | |||
1362 | length = sizeof(struct in_addr); | |||
1363 | family = AF_INET2; | |||
1364 | } else if (uv_inet_pton(AF_INET610, name, &address_buffer) == 0) { | |||
1365 | length = sizeof(struct in6_addr); | |||
1366 | family = AF_INET610; | |||
1367 | } else { | |||
1368 | return UV_EINVAL; // So errnoException() reports a proper error. | |||
1369 | } | |||
1370 | ||||
1371 | TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(do { static std::atomic<intptr_t> trace_event_unique_atomic1374 {0}; const uint8_t* trace_event_unique_category_group_enabled1374 ; trace_event_unique_category_group_enabled1374 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic1374).load() ); if (!trace_event_unique_category_group_enabled1374) { trace_event_unique_category_group_enabled1374 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "dns" "," "node" "." "dns" "." "native"); (trace_event_unique_atomic1374 ).store(reinterpret_cast<intptr_t>( trace_event_unique_category_group_enabled1374 )); };; if (*trace_event_unique_category_group_enabled1374 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags )) { unsigned int trace_event_flags = (static_cast<unsigned int>(0)) | (static_cast<unsigned int>(1 << 1) ); node::tracing::TraceID trace_event_trace_id(wrap, &trace_event_flags ); node::tracing::AddTraceEvent( ('b'), trace_event_unique_category_group_enabled1374 , "reverse", trace_event_trace_id.scope(), trace_event_trace_id .raw_id(), node::tracing::kNoId, trace_event_flags, "name", node ::tracing::TraceStringWithCopy(name), "family", family == 2 ? "ipv4" : "ipv6"); } } while (0) | |||
1372 | TRACING_CATEGORY_NODE2(dns, native), "reverse", wrap,do { static std::atomic<intptr_t> trace_event_unique_atomic1374 {0}; const uint8_t* trace_event_unique_category_group_enabled1374 ; trace_event_unique_category_group_enabled1374 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic1374).load() ); if (!trace_event_unique_category_group_enabled1374) { trace_event_unique_category_group_enabled1374 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "dns" "," "node" "." "dns" "." "native"); (trace_event_unique_atomic1374 ).store(reinterpret_cast<intptr_t>( trace_event_unique_category_group_enabled1374 )); };; if (*trace_event_unique_category_group_enabled1374 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags )) { unsigned int trace_event_flags = (static_cast<unsigned int>(0)) | (static_cast<unsigned int>(1 << 1) ); node::tracing::TraceID trace_event_trace_id(wrap, &trace_event_flags ); node::tracing::AddTraceEvent( ('b'), trace_event_unique_category_group_enabled1374 , "reverse", trace_event_trace_id.scope(), trace_event_trace_id .raw_id(), node::tracing::kNoId, trace_event_flags, "name", node ::tracing::TraceStringWithCopy(name), "family", family == 2 ? "ipv4" : "ipv6"); } } while (0) | |||
1373 | "name", TRACE_STR_COPY(name),do { static std::atomic<intptr_t> trace_event_unique_atomic1374 {0}; const uint8_t* trace_event_unique_category_group_enabled1374 ; trace_event_unique_category_group_enabled1374 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic1374).load() ); if (!trace_event_unique_category_group_enabled1374) { trace_event_unique_category_group_enabled1374 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "dns" "," "node" "." "dns" "." "native"); (trace_event_unique_atomic1374 ).store(reinterpret_cast<intptr_t>( trace_event_unique_category_group_enabled1374 )); };; if (*trace_event_unique_category_group_enabled1374 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags )) { unsigned int trace_event_flags = (static_cast<unsigned int>(0)) | (static_cast<unsigned int>(1 << 1) ); node::tracing::TraceID trace_event_trace_id(wrap, &trace_event_flags ); node::tracing::AddTraceEvent( ('b'), trace_event_unique_category_group_enabled1374 , "reverse", trace_event_trace_id.scope(), trace_event_trace_id .raw_id(), node::tracing::kNoId, trace_event_flags, "name", node ::tracing::TraceStringWithCopy(name), "family", family == 2 ? "ipv4" : "ipv6"); } } while (0) | |||
1374 | "family", family == AF_INET ? "ipv4" : "ipv6")do { static std::atomic<intptr_t> trace_event_unique_atomic1374 {0}; const uint8_t* trace_event_unique_category_group_enabled1374 ; trace_event_unique_category_group_enabled1374 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic1374).load() ); if (!trace_event_unique_category_group_enabled1374) { trace_event_unique_category_group_enabled1374 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "dns" "," "node" "." "dns" "." "native"); (trace_event_unique_atomic1374 ).store(reinterpret_cast<intptr_t>( trace_event_unique_category_group_enabled1374 )); };; if (*trace_event_unique_category_group_enabled1374 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags )) { unsigned int trace_event_flags = (static_cast<unsigned int>(0)) | (static_cast<unsigned int>(1 << 1) ); node::tracing::TraceID trace_event_trace_id(wrap, &trace_event_flags ); node::tracing::AddTraceEvent( ('b'), trace_event_unique_category_group_enabled1374 , "reverse", trace_event_trace_id.scope(), trace_event_trace_id .raw_id(), node::tracing::kNoId, trace_event_flags, "name", node ::tracing::TraceStringWithCopy(name), "family", family == 2 ? "ipv4" : "ipv6"); } } while (0); | |||
1375 | ||||
1376 | ares_gethostbyaddr( | |||
1377 | wrap->channel()->cares_channel(), | |||
1378 | address_buffer, | |||
1379 | length, | |||
1380 | family, | |||
1381 | GetHostByAddrWrap::Callback, | |||
1382 | wrap->MakeCallbackPointer()); | |||
1383 | return 0; | |||
1384 | } | |||
1385 | ||||
1386 | int ReverseTraits::Parse( | |||
1387 | GetHostByAddrWrap* wrap, | |||
1388 | const std::unique_ptr<ResponseData>& response) { | |||
1389 | if (UNLIKELY(!response->is_host)__builtin_expect(!!(!response->is_host), 0)) | |||
1390 | return ARES_EBADRESP10; | |||
1391 | ||||
1392 | struct hostent* host = response->host.get(); | |||
1393 | ||||
1394 | Environment* env = wrap->env(); | |||
1395 | HandleScope handle_scope(env->isolate()); | |||
1396 | Context::Scope context_scope(env->context()); | |||
1397 | wrap->CallOnComplete(HostentToNames(env, host)); | |||
1398 | return 0; | |||
1399 | } | |||
1400 | ||||
1401 | namespace { | |||
1402 | template <class Wrap> | |||
1403 | static void Query(const FunctionCallbackInfo<Value>& args) { | |||
1404 | Environment* env = Environment::GetCurrent(args); | |||
1405 | ChannelWrap* channel; | |||
1406 | ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder())do { *&channel = static_cast<typename std::remove_reference <decltype(*&channel)>::type>( BaseObject::FromJSObject (args.Holder())); if (*&channel == nullptr) return ; } while (0); | |||
1407 | ||||
1408 | CHECK_EQ(false, args.IsConstructCall())do { if (__builtin_expect(!!(!((false) == (args.IsConstructCall ()))), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1408", "(false) == (args.IsConstructCall())", __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
1409 | CHECK(args[0]->IsObject())do { if (__builtin_expect(!!(!(args[0]->IsObject())), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1409", "args[0]->IsObject()", __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
1410 | CHECK(args[1]->IsString())do { if (__builtin_expect(!!(!(args[1]->IsString())), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1410", "args[1]->IsString()", __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
1411 | ||||
1412 | Local<Object> req_wrap_obj = args[0].As<Object>(); | |||
1413 | Local<String> string = args[1].As<String>(); | |||
1414 | auto wrap = std::make_unique<Wrap>(channel, req_wrap_obj); | |||
1415 | ||||
1416 | node::Utf8Value name(env->isolate(), string); | |||
1417 | channel->ModifyActivityQueryCount(1); | |||
1418 | int err = wrap->Send(*name); | |||
1419 | if (err) { | |||
1420 | channel->ModifyActivityQueryCount(-1); | |||
1421 | } else { | |||
1422 | // Release ownership of the pointer allowing the ownership to be transferred | |||
1423 | USE(wrap.release()); | |||
1424 | } | |||
1425 | ||||
1426 | args.GetReturnValue().Set(err); | |||
1427 | } | |||
1428 | ||||
1429 | ||||
1430 | void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) { | |||
1431 | std::unique_ptr<GetAddrInfoReqWrap> req_wrap { | |||
1432 | static_cast<GetAddrInfoReqWrap*>(req->data)}; | |||
1433 | Environment* env = req_wrap->env(); | |||
1434 | ||||
1435 | HandleScope handle_scope(env->isolate()); | |||
1436 | Context::Scope context_scope(env->context()); | |||
1437 | ||||
1438 | Local<Value> argv[] = { | |||
1439 | Integer::New(env->isolate(), status), | |||
1440 | Null(env->isolate()) | |||
1441 | }; | |||
1442 | ||||
1443 | uint32_t n = 0; | |||
1444 | const bool verbatim = req_wrap->verbatim(); | |||
1445 | ||||
1446 | if (status == 0) { | |||
1447 | Local<Array> results = Array::New(env->isolate()); | |||
1448 | ||||
1449 | auto add = [&] (bool want_ipv4, bool want_ipv6) -> Maybe<bool> { | |||
1450 | for (auto p = res; p != nullptr; p = p->ai_next) { | |||
1451 | CHECK_EQ(p->ai_socktype, SOCK_STREAM)do { if (__builtin_expect(!!(!((p->ai_socktype) == (SOCK_STREAM ))), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1451", "(p->ai_socktype) == (SOCK_STREAM)", __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
1452 | ||||
1453 | const char* addr; | |||
1454 | if (want_ipv4 && p->ai_family == AF_INET2) { | |||
1455 | addr = reinterpret_cast<char*>( | |||
1456 | &(reinterpret_cast<struct sockaddr_in*>(p->ai_addr)->sin_addr)); | |||
1457 | } else if (want_ipv6 && p->ai_family == AF_INET610) { | |||
1458 | addr = reinterpret_cast<char*>( | |||
1459 | &(reinterpret_cast<struct sockaddr_in6*>(p->ai_addr)->sin6_addr)); | |||
1460 | } else { | |||
1461 | continue; | |||
1462 | } | |||
1463 | ||||
1464 | char ip[INET6_ADDRSTRLEN46]; | |||
1465 | if (uv_inet_ntop(p->ai_family, addr, ip, sizeof(ip))) | |||
1466 | continue; | |||
1467 | ||||
1468 | Local<String> s = OneByteString(env->isolate(), ip); | |||
1469 | if (results->Set(env->context(), n, s).IsNothing()) | |||
1470 | return Nothing<bool>(); | |||
1471 | n++; | |||
1472 | } | |||
1473 | return Just(true); | |||
1474 | }; | |||
1475 | ||||
1476 | if (add(true, verbatim).IsNothing()) | |||
1477 | return; | |||
1478 | if (verbatim == false) { | |||
1479 | if (add(false, true).IsNothing()) | |||
1480 | return; | |||
1481 | } | |||
1482 | ||||
1483 | // No responses were found to return | |||
1484 | if (n == 0) { | |||
1485 | argv[0] = Integer::New(env->isolate(), UV_EAI_NODATA); | |||
1486 | } | |||
1487 | ||||
1488 | argv[1] = results; | |||
1489 | } | |||
1490 | ||||
1491 | uv_freeaddrinfo(res); | |||
1492 | ||||
1493 | TRACE_EVENT_NESTABLE_ASYNC_END2(do { static std::atomic<intptr_t> trace_event_unique_atomic1495 {0}; const uint8_t* trace_event_unique_category_group_enabled1495 ; trace_event_unique_category_group_enabled1495 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic1495).load() ); if (!trace_event_unique_category_group_enabled1495) { trace_event_unique_category_group_enabled1495 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "dns" "," "node" "." "dns" "." "native"); (trace_event_unique_atomic1495 ).store(reinterpret_cast<intptr_t>( trace_event_unique_category_group_enabled1495 )); };; if (*trace_event_unique_category_group_enabled1495 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags )) { unsigned int trace_event_flags = (static_cast<unsigned int>(0)) | (static_cast<unsigned int>(1 << 1) ); node::tracing::TraceID trace_event_trace_id(req_wrap.get() , &trace_event_flags); node::tracing::AddTraceEvent( ('e' ), trace_event_unique_category_group_enabled1495, "lookup", trace_event_trace_id .scope(), trace_event_trace_id.raw_id(), node::tracing::kNoId , trace_event_flags, "count", n, "verbatim", verbatim); } } while (0) | |||
1494 | TRACING_CATEGORY_NODE2(dns, native), "lookup", req_wrap.get(),do { static std::atomic<intptr_t> trace_event_unique_atomic1495 {0}; const uint8_t* trace_event_unique_category_group_enabled1495 ; trace_event_unique_category_group_enabled1495 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic1495).load() ); if (!trace_event_unique_category_group_enabled1495) { trace_event_unique_category_group_enabled1495 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "dns" "," "node" "." "dns" "." "native"); (trace_event_unique_atomic1495 ).store(reinterpret_cast<intptr_t>( trace_event_unique_category_group_enabled1495 )); };; if (*trace_event_unique_category_group_enabled1495 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags )) { unsigned int trace_event_flags = (static_cast<unsigned int>(0)) | (static_cast<unsigned int>(1 << 1) ); node::tracing::TraceID trace_event_trace_id(req_wrap.get() , &trace_event_flags); node::tracing::AddTraceEvent( ('e' ), trace_event_unique_category_group_enabled1495, "lookup", trace_event_trace_id .scope(), trace_event_trace_id.raw_id(), node::tracing::kNoId , trace_event_flags, "count", n, "verbatim", verbatim); } } while (0) | |||
1495 | "count", n, "verbatim", verbatim)do { static std::atomic<intptr_t> trace_event_unique_atomic1495 {0}; const uint8_t* trace_event_unique_category_group_enabled1495 ; trace_event_unique_category_group_enabled1495 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic1495).load() ); if (!trace_event_unique_category_group_enabled1495) { trace_event_unique_category_group_enabled1495 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "dns" "," "node" "." "dns" "." "native"); (trace_event_unique_atomic1495 ).store(reinterpret_cast<intptr_t>( trace_event_unique_category_group_enabled1495 )); };; if (*trace_event_unique_category_group_enabled1495 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags )) { unsigned int trace_event_flags = (static_cast<unsigned int>(0)) | (static_cast<unsigned int>(1 << 1) ); node::tracing::TraceID trace_event_trace_id(req_wrap.get() , &trace_event_flags); node::tracing::AddTraceEvent( ('e' ), trace_event_unique_category_group_enabled1495, "lookup", trace_event_trace_id .scope(), trace_event_trace_id.raw_id(), node::tracing::kNoId , trace_event_flags, "count", n, "verbatim", verbatim); } } while (0); | |||
1496 | ||||
1497 | // Make the callback into JavaScript | |||
1498 | req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv); | |||
1499 | } | |||
1500 | ||||
1501 | ||||
1502 | void AfterGetNameInfo(uv_getnameinfo_t* req, | |||
1503 | int status, | |||
1504 | const char* hostname, | |||
1505 | const char* service) { | |||
1506 | std::unique_ptr<GetNameInfoReqWrap> req_wrap { | |||
1507 | static_cast<GetNameInfoReqWrap*>(req->data)}; | |||
1508 | Environment* env = req_wrap->env(); | |||
1509 | ||||
1510 | HandleScope handle_scope(env->isolate()); | |||
1511 | 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 | }; | |||
1518 | ||||
1519 | if (status == 0) { | |||
1520 | // Success | |||
1521 | Local<String> js_hostname = OneByteString(env->isolate(), hostname); | |||
1522 | Local<String> js_service = OneByteString(env->isolate(), service); | |||
1523 | argv[1] = js_hostname; | |||
1524 | argv[2] = js_service; | |||
1525 | } | |||
1526 | ||||
1527 | TRACE_EVENT_NESTABLE_ASYNC_END2(do { static std::atomic<intptr_t> trace_event_unique_atomic1530 {0}; const uint8_t* trace_event_unique_category_group_enabled1530 ; trace_event_unique_category_group_enabled1530 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic1530).load() ); if (!trace_event_unique_category_group_enabled1530) { trace_event_unique_category_group_enabled1530 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "dns" "," "node" "." "dns" "." "native"); (trace_event_unique_atomic1530 ).store(reinterpret_cast<intptr_t>( trace_event_unique_category_group_enabled1530 )); };; if (*trace_event_unique_category_group_enabled1530 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags )) { unsigned int trace_event_flags = (static_cast<unsigned int>(0)) | (static_cast<unsigned int>(1 << 1) ); node::tracing::TraceID trace_event_trace_id(req_wrap.get() , &trace_event_flags); node::tracing::AddTraceEvent( ('e' ), trace_event_unique_category_group_enabled1530, "lookupService" , trace_event_trace_id.scope(), trace_event_trace_id.raw_id() , node::tracing::kNoId, trace_event_flags, "hostname", node:: tracing::TraceStringWithCopy(hostname), "service", node::tracing ::TraceStringWithCopy(service)); } } while (0) | |||
1528 | TRACING_CATEGORY_NODE2(dns, native), "lookupService", req_wrap.get(),do { static std::atomic<intptr_t> trace_event_unique_atomic1530 {0}; const uint8_t* trace_event_unique_category_group_enabled1530 ; trace_event_unique_category_group_enabled1530 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic1530).load() ); if (!trace_event_unique_category_group_enabled1530) { trace_event_unique_category_group_enabled1530 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "dns" "," "node" "." "dns" "." "native"); (trace_event_unique_atomic1530 ).store(reinterpret_cast<intptr_t>( trace_event_unique_category_group_enabled1530 )); };; if (*trace_event_unique_category_group_enabled1530 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags )) { unsigned int trace_event_flags = (static_cast<unsigned int>(0)) | (static_cast<unsigned int>(1 << 1) ); node::tracing::TraceID trace_event_trace_id(req_wrap.get() , &trace_event_flags); node::tracing::AddTraceEvent( ('e' ), trace_event_unique_category_group_enabled1530, "lookupService" , trace_event_trace_id.scope(), trace_event_trace_id.raw_id() , node::tracing::kNoId, trace_event_flags, "hostname", node:: tracing::TraceStringWithCopy(hostname), "service", node::tracing ::TraceStringWithCopy(service)); } } while (0) | |||
1529 | "hostname", TRACE_STR_COPY(hostname),do { static std::atomic<intptr_t> trace_event_unique_atomic1530 {0}; const uint8_t* trace_event_unique_category_group_enabled1530 ; trace_event_unique_category_group_enabled1530 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic1530).load() ); if (!trace_event_unique_category_group_enabled1530) { trace_event_unique_category_group_enabled1530 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "dns" "," "node" "." "dns" "." "native"); (trace_event_unique_atomic1530 ).store(reinterpret_cast<intptr_t>( trace_event_unique_category_group_enabled1530 )); };; if (*trace_event_unique_category_group_enabled1530 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags )) { unsigned int trace_event_flags = (static_cast<unsigned int>(0)) | (static_cast<unsigned int>(1 << 1) ); node::tracing::TraceID trace_event_trace_id(req_wrap.get() , &trace_event_flags); node::tracing::AddTraceEvent( ('e' ), trace_event_unique_category_group_enabled1530, "lookupService" , trace_event_trace_id.scope(), trace_event_trace_id.raw_id() , node::tracing::kNoId, trace_event_flags, "hostname", node:: tracing::TraceStringWithCopy(hostname), "service", node::tracing ::TraceStringWithCopy(service)); } } while (0) | |||
1530 | "service", TRACE_STR_COPY(service))do { static std::atomic<intptr_t> trace_event_unique_atomic1530 {0}; const uint8_t* trace_event_unique_category_group_enabled1530 ; trace_event_unique_category_group_enabled1530 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic1530).load() ); if (!trace_event_unique_category_group_enabled1530) { trace_event_unique_category_group_enabled1530 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "dns" "," "node" "." "dns" "." "native"); (trace_event_unique_atomic1530 ).store(reinterpret_cast<intptr_t>( trace_event_unique_category_group_enabled1530 )); };; if (*trace_event_unique_category_group_enabled1530 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags )) { unsigned int trace_event_flags = (static_cast<unsigned int>(0)) | (static_cast<unsigned int>(1 << 1) ); node::tracing::TraceID trace_event_trace_id(req_wrap.get() , &trace_event_flags); node::tracing::AddTraceEvent( ('e' ), trace_event_unique_category_group_enabled1530, "lookupService" , trace_event_trace_id.scope(), trace_event_trace_id.raw_id() , node::tracing::kNoId, trace_event_flags, "hostname", node:: tracing::TraceStringWithCopy(hostname), "service", node::tracing ::TraceStringWithCopy(service)); } } while (0); | |||
1531 | ||||
1532 | // Make the callback into JavaScript | |||
1533 | req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv); | |||
1534 | } | |||
1535 | ||||
1536 | using ParseIPResult = | |||
1537 | decltype(static_cast<ares_addr_port_node*>(nullptr)->addr); | |||
1538 | ||||
1539 | int ParseIP(const char* ip, ParseIPResult* result = nullptr) { | |||
1540 | ParseIPResult tmp; | |||
1541 | if (result == nullptr) result = &tmp; | |||
1542 | if (0 == uv_inet_pton(AF_INET2, ip, result)) return 4; | |||
1543 | if (0 == uv_inet_pton(AF_INET610, ip, result)) return 6; | |||
1544 | return 0; | |||
1545 | } | |||
1546 | ||||
1547 | void CanonicalizeIP(const FunctionCallbackInfo<Value>& args) { | |||
1548 | Isolate* isolate = args.GetIsolate(); | |||
1549 | node::Utf8Value ip(isolate, args[0]); | |||
1550 | ||||
1551 | ParseIPResult result; | |||
1552 | const int rc = ParseIP(*ip, &result); | |||
1553 | if (rc == 0) return; | |||
1554 | ||||
1555 | char canonical_ip[INET6_ADDRSTRLEN46]; | |||
1556 | const int af = (rc == 4 ? AF_INET2 : AF_INET610); | |||
1557 | CHECK_EQ(0, uv_inet_ntop(af, &result, canonical_ip, sizeof(canonical_ip)))do { if (__builtin_expect(!!(!((0) == (uv_inet_ntop(af, & result, canonical_ip, sizeof(canonical_ip))))), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1557", "(0) == (uv_inet_ntop(af, &result, canonical_ip, sizeof(canonical_ip)))" , __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
1558 | Local<String> val = String::NewFromUtf8(isolate, canonical_ip) | |||
1559 | .ToLocalChecked(); | |||
1560 | args.GetReturnValue().Set(val); | |||
1561 | } | |||
1562 | ||||
1563 | void GetAddrInfo(const FunctionCallbackInfo<Value>& args) { | |||
1564 | Environment* env = Environment::GetCurrent(args); | |||
1565 | ||||
1566 | CHECK(args[0]->IsObject())do { if (__builtin_expect(!!(!(args[0]->IsObject())), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1566", "args[0]->IsObject()", __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
1567 | CHECK(args[1]->IsString())do { if (__builtin_expect(!!(!(args[1]->IsString())), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1567", "args[1]->IsString()", __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
1568 | CHECK(args[2]->IsInt32())do { if (__builtin_expect(!!(!(args[2]->IsInt32())), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1568", "args[2]->IsInt32()", __PRETTY_FUNCTION__ }; node ::Assert(args); } while (0); } } while (0); | |||
1569 | CHECK(args[4]->IsBoolean())do { if (__builtin_expect(!!(!(args[4]->IsBoolean())), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1569", "args[4]->IsBoolean()", __PRETTY_FUNCTION__ } ; node::Assert(args); } while (0); } } while (0); | |||
1570 | Local<Object> req_wrap_obj = args[0].As<Object>(); | |||
1571 | node::Utf8Value hostname(env->isolate(), args[1]); | |||
1572 | ||||
1573 | int32_t flags = 0; | |||
1574 | if (args[3]->IsInt32()) { | |||
1575 | flags = args[3].As<Int32>()->Value(); | |||
1576 | } | |||
1577 | ||||
1578 | int family; | |||
1579 | ||||
1580 | switch (args[2].As<Int32>()->Value()) { | |||
1581 | case 0: | |||
1582 | family = AF_UNSPEC0; | |||
1583 | break; | |||
1584 | case 4: | |||
1585 | family = AF_INET2; | |||
1586 | break; | |||
1587 | case 6: | |||
1588 | family = AF_INET610; | |||
1589 | break; | |||
1590 | default: | |||
1591 | CHECK(0 && "bad address family")do { if (__builtin_expect(!!(!(0 && "bad address family" )), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1591", "0 && \"bad address family\"", __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
1592 | } | |||
1593 | ||||
1594 | auto req_wrap = std::make_unique<GetAddrInfoReqWrap>(env, | |||
1595 | req_wrap_obj, | |||
1596 | args[4]->IsTrue()); | |||
1597 | ||||
1598 | struct addrinfo hints; | |||
1599 | memset(&hints, 0, sizeof(hints)); | |||
1600 | hints.ai_family = family; | |||
1601 | hints.ai_socktype = SOCK_STREAMSOCK_STREAM; | |||
1602 | hints.ai_flags = flags; | |||
1603 | ||||
1604 | TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(do { static std::atomic<intptr_t> trace_event_unique_atomic1608 {0}; const uint8_t* trace_event_unique_category_group_enabled1608 ; trace_event_unique_category_group_enabled1608 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic1608).load() ); if (!trace_event_unique_category_group_enabled1608) { trace_event_unique_category_group_enabled1608 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "dns" "," "node" "." "dns" "." "native"); (trace_event_unique_atomic1608 ).store(reinterpret_cast<intptr_t>( trace_event_unique_category_group_enabled1608 )); };; if (*trace_event_unique_category_group_enabled1608 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags )) { unsigned int trace_event_flags = (static_cast<unsigned int>(0)) | (static_cast<unsigned int>(1 << 1) ); node::tracing::TraceID trace_event_trace_id(req_wrap.get() , &trace_event_flags); node::tracing::AddTraceEvent( ('b' ), trace_event_unique_category_group_enabled1608, "lookup", trace_event_trace_id .scope(), trace_event_trace_id.raw_id(), node::tracing::kNoId , trace_event_flags, "hostname", node::tracing::TraceStringWithCopy (*hostname), "family", family == 2 ? "ipv4" : family == 10 ? "ipv6" : "unspec"); } } while (0) | |||
1605 | TRACING_CATEGORY_NODE2(dns, native), "lookup", req_wrap.get(),do { static std::atomic<intptr_t> trace_event_unique_atomic1608 {0}; const uint8_t* trace_event_unique_category_group_enabled1608 ; trace_event_unique_category_group_enabled1608 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic1608).load() ); if (!trace_event_unique_category_group_enabled1608) { trace_event_unique_category_group_enabled1608 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "dns" "," "node" "." "dns" "." "native"); (trace_event_unique_atomic1608 ).store(reinterpret_cast<intptr_t>( trace_event_unique_category_group_enabled1608 )); };; if (*trace_event_unique_category_group_enabled1608 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags )) { unsigned int trace_event_flags = (static_cast<unsigned int>(0)) | (static_cast<unsigned int>(1 << 1) ); node::tracing::TraceID trace_event_trace_id(req_wrap.get() , &trace_event_flags); node::tracing::AddTraceEvent( ('b' ), trace_event_unique_category_group_enabled1608, "lookup", trace_event_trace_id .scope(), trace_event_trace_id.raw_id(), node::tracing::kNoId , trace_event_flags, "hostname", node::tracing::TraceStringWithCopy (*hostname), "family", family == 2 ? "ipv4" : family == 10 ? "ipv6" : "unspec"); } } while (0) | |||
1606 | "hostname", TRACE_STR_COPY(*hostname),do { static std::atomic<intptr_t> trace_event_unique_atomic1608 {0}; const uint8_t* trace_event_unique_category_group_enabled1608 ; trace_event_unique_category_group_enabled1608 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic1608).load() ); if (!trace_event_unique_category_group_enabled1608) { trace_event_unique_category_group_enabled1608 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "dns" "," "node" "." "dns" "." "native"); (trace_event_unique_atomic1608 ).store(reinterpret_cast<intptr_t>( trace_event_unique_category_group_enabled1608 )); };; if (*trace_event_unique_category_group_enabled1608 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags )) { unsigned int trace_event_flags = (static_cast<unsigned int>(0)) | (static_cast<unsigned int>(1 << 1) ); node::tracing::TraceID trace_event_trace_id(req_wrap.get() , &trace_event_flags); node::tracing::AddTraceEvent( ('b' ), trace_event_unique_category_group_enabled1608, "lookup", trace_event_trace_id .scope(), trace_event_trace_id.raw_id(), node::tracing::kNoId , trace_event_flags, "hostname", node::tracing::TraceStringWithCopy (*hostname), "family", family == 2 ? "ipv4" : family == 10 ? "ipv6" : "unspec"); } } while (0) | |||
1607 | "family",do { static std::atomic<intptr_t> trace_event_unique_atomic1608 {0}; const uint8_t* trace_event_unique_category_group_enabled1608 ; trace_event_unique_category_group_enabled1608 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic1608).load() ); if (!trace_event_unique_category_group_enabled1608) { trace_event_unique_category_group_enabled1608 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "dns" "," "node" "." "dns" "." "native"); (trace_event_unique_atomic1608 ).store(reinterpret_cast<intptr_t>( trace_event_unique_category_group_enabled1608 )); };; if (*trace_event_unique_category_group_enabled1608 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags )) { unsigned int trace_event_flags = (static_cast<unsigned int>(0)) | (static_cast<unsigned int>(1 << 1) ); node::tracing::TraceID trace_event_trace_id(req_wrap.get() , &trace_event_flags); node::tracing::AddTraceEvent( ('b' ), trace_event_unique_category_group_enabled1608, "lookup", trace_event_trace_id .scope(), trace_event_trace_id.raw_id(), node::tracing::kNoId , trace_event_flags, "hostname", node::tracing::TraceStringWithCopy (*hostname), "family", family == 2 ? "ipv4" : family == 10 ? "ipv6" : "unspec"); } } while (0) | |||
1608 | family == AF_INET ? "ipv4" : family == AF_INET6 ? "ipv6" : "unspec")do { static std::atomic<intptr_t> trace_event_unique_atomic1608 {0}; const uint8_t* trace_event_unique_category_group_enabled1608 ; trace_event_unique_category_group_enabled1608 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic1608).load() ); if (!trace_event_unique_category_group_enabled1608) { trace_event_unique_category_group_enabled1608 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "dns" "," "node" "." "dns" "." "native"); (trace_event_unique_atomic1608 ).store(reinterpret_cast<intptr_t>( trace_event_unique_category_group_enabled1608 )); };; if (*trace_event_unique_category_group_enabled1608 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags )) { unsigned int trace_event_flags = (static_cast<unsigned int>(0)) | (static_cast<unsigned int>(1 << 1) ); node::tracing::TraceID trace_event_trace_id(req_wrap.get() , &trace_event_flags); node::tracing::AddTraceEvent( ('b' ), trace_event_unique_category_group_enabled1608, "lookup", trace_event_trace_id .scope(), trace_event_trace_id.raw_id(), node::tracing::kNoId , trace_event_flags, "hostname", node::tracing::TraceStringWithCopy (*hostname), "family", family == 2 ? "ipv4" : family == 10 ? "ipv6" : "unspec"); } } while (0); | |||
1609 | ||||
1610 | int err = req_wrap->Dispatch(uv_getaddrinfo, | |||
1611 | AfterGetAddrInfo, | |||
1612 | *hostname, | |||
1613 | nullptr, | |||
1614 | &hints); | |||
1615 | if (err == 0) | |||
1616 | // Release ownership of the pointer allowing the ownership to be transferred | |||
1617 | USE(req_wrap.release()); | |||
1618 | ||||
1619 | args.GetReturnValue().Set(err); | |||
1620 | } | |||
1621 | ||||
1622 | ||||
1623 | void GetNameInfo(const FunctionCallbackInfo<Value>& args) { | |||
1624 | Environment* env = Environment::GetCurrent(args); | |||
1625 | ||||
1626 | CHECK(args[0]->IsObject())do { if (__builtin_expect(!!(!(args[0]->IsObject())), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1626", "args[0]->IsObject()", __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
1627 | CHECK(args[1]->IsString())do { if (__builtin_expect(!!(!(args[1]->IsString())), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1627", "args[1]->IsString()", __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
1628 | CHECK(args[2]->IsUint32())do { if (__builtin_expect(!!(!(args[2]->IsUint32())), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1628", "args[2]->IsUint32()", __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
1629 | Local<Object> req_wrap_obj = args[0].As<Object>(); | |||
1630 | node::Utf8Value ip(env->isolate(), args[1]); | |||
1631 | const unsigned port = args[2]->Uint32Value(env->context()).FromJust(); | |||
1632 | struct sockaddr_storage addr; | |||
1633 | ||||
1634 | CHECK(uv_ip4_addr(*ip, port, reinterpret_cast<sockaddr_in*>(&addr)) == 0 ||do { if (__builtin_expect(!!(!(uv_ip4_addr(*ip, port, reinterpret_cast <sockaddr_in*>(&addr)) == 0 || uv_ip6_addr(*ip, port , reinterpret_cast<sockaddr_in6*>(&addr)) == 0)), 0 )) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1635", "uv_ip4_addr(*ip, port, reinterpret_cast<sockaddr_in*>(&addr)) == 0 || uv_ip6_addr(*ip, port, reinterpret_cast<sockaddr_in6*>(&addr)) == 0" , __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0) | |||
1635 | uv_ip6_addr(*ip, port, reinterpret_cast<sockaddr_in6*>(&addr)) == 0)do { if (__builtin_expect(!!(!(uv_ip4_addr(*ip, port, reinterpret_cast <sockaddr_in*>(&addr)) == 0 || uv_ip6_addr(*ip, port , reinterpret_cast<sockaddr_in6*>(&addr)) == 0)), 0 )) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1635", "uv_ip4_addr(*ip, port, reinterpret_cast<sockaddr_in*>(&addr)) == 0 || uv_ip6_addr(*ip, port, reinterpret_cast<sockaddr_in6*>(&addr)) == 0" , __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
1636 | ||||
1637 | auto req_wrap = std::make_unique<GetNameInfoReqWrap>(env, req_wrap_obj); | |||
1638 | ||||
1639 | TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(do { static std::atomic<intptr_t> trace_event_unique_atomic1641 {0}; const uint8_t* trace_event_unique_category_group_enabled1641 ; trace_event_unique_category_group_enabled1641 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic1641).load() ); if (!trace_event_unique_category_group_enabled1641) { trace_event_unique_category_group_enabled1641 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "dns" "," "node" "." "dns" "." "native"); (trace_event_unique_atomic1641 ).store(reinterpret_cast<intptr_t>( trace_event_unique_category_group_enabled1641 )); };; if (*trace_event_unique_category_group_enabled1641 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags )) { unsigned int trace_event_flags = (static_cast<unsigned int>(0)) | (static_cast<unsigned int>(1 << 1) ); node::tracing::TraceID trace_event_trace_id(req_wrap.get() , &trace_event_flags); node::tracing::AddTraceEvent( ('b' ), trace_event_unique_category_group_enabled1641, "lookupService" , trace_event_trace_id.scope(), trace_event_trace_id.raw_id() , node::tracing::kNoId, trace_event_flags, "ip", node::tracing ::TraceStringWithCopy(*ip), "port", port); } } while (0) | |||
1640 | TRACING_CATEGORY_NODE2(dns, native), "lookupService", req_wrap.get(),do { static std::atomic<intptr_t> trace_event_unique_atomic1641 {0}; const uint8_t* trace_event_unique_category_group_enabled1641 ; trace_event_unique_category_group_enabled1641 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic1641).load() ); if (!trace_event_unique_category_group_enabled1641) { trace_event_unique_category_group_enabled1641 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "dns" "," "node" "." "dns" "." "native"); (trace_event_unique_atomic1641 ).store(reinterpret_cast<intptr_t>( trace_event_unique_category_group_enabled1641 )); };; if (*trace_event_unique_category_group_enabled1641 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags )) { unsigned int trace_event_flags = (static_cast<unsigned int>(0)) | (static_cast<unsigned int>(1 << 1) ); node::tracing::TraceID trace_event_trace_id(req_wrap.get() , &trace_event_flags); node::tracing::AddTraceEvent( ('b' ), trace_event_unique_category_group_enabled1641, "lookupService" , trace_event_trace_id.scope(), trace_event_trace_id.raw_id() , node::tracing::kNoId, trace_event_flags, "ip", node::tracing ::TraceStringWithCopy(*ip), "port", port); } } while (0) | |||
1641 | "ip", TRACE_STR_COPY(*ip), "port", port)do { static std::atomic<intptr_t> trace_event_unique_atomic1641 {0}; const uint8_t* trace_event_unique_category_group_enabled1641 ; trace_event_unique_category_group_enabled1641 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic1641).load() ); if (!trace_event_unique_category_group_enabled1641) { trace_event_unique_category_group_enabled1641 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "dns" "," "node" "." "dns" "." "native"); (trace_event_unique_atomic1641 ).store(reinterpret_cast<intptr_t>( trace_event_unique_category_group_enabled1641 )); };; if (*trace_event_unique_category_group_enabled1641 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags )) { unsigned int trace_event_flags = (static_cast<unsigned int>(0)) | (static_cast<unsigned int>(1 << 1) ); node::tracing::TraceID trace_event_trace_id(req_wrap.get() , &trace_event_flags); node::tracing::AddTraceEvent( ('b' ), trace_event_unique_category_group_enabled1641, "lookupService" , trace_event_trace_id.scope(), trace_event_trace_id.raw_id() , node::tracing::kNoId, trace_event_flags, "ip", node::tracing ::TraceStringWithCopy(*ip), "port", port); } } while (0); | |||
1642 | ||||
1643 | int err = req_wrap->Dispatch(uv_getnameinfo, | |||
1644 | AfterGetNameInfo, | |||
1645 | reinterpret_cast<struct sockaddr*>(&addr), | |||
1646 | NI_NAMEREQD8); | |||
1647 | if (err == 0) | |||
1648 | // Release ownership of the pointer allowing the ownership to be transferred | |||
1649 | USE(req_wrap.release()); | |||
1650 | ||||
1651 | args.GetReturnValue().Set(err); | |||
1652 | } | |||
1653 | ||||
1654 | ||||
1655 | void GetServers(const FunctionCallbackInfo<Value>& args) { | |||
1656 | Environment* env = Environment::GetCurrent(args); | |||
1657 | ChannelWrap* channel; | |||
1658 | ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder())do { *&channel = static_cast<typename std::remove_reference <decltype(*&channel)>::type>( BaseObject::FromJSObject (args.Holder())); if (*&channel == nullptr) return ; } while (0); | |||
1659 | ||||
1660 | Local<Array> server_array = Array::New(env->isolate()); | |||
1661 | ||||
1662 | ares_addr_port_node* servers; | |||
1663 | ||||
1664 | int r = ares_get_servers_ports(channel->cares_channel(), &servers); | |||
1665 | CHECK_EQ(r, ARES_SUCCESS)do { if (__builtin_expect(!!(!((r) == (0))), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1665", "(r) == (0)", __PRETTY_FUNCTION__ }; node::Assert(args ); } while (0); } } while (0); | |||
1666 | auto cleanup = OnScopeLeave([&]() { ares_free_data(servers); }); | |||
1667 | ||||
1668 | ares_addr_port_node* cur = servers; | |||
1669 | ||||
1670 | for (uint32_t i = 0; cur != nullptr; ++i, cur = cur->next) { | |||
1671 | char ip[INET6_ADDRSTRLEN46]; | |||
1672 | ||||
1673 | const void* caddr = static_cast<const void*>(&cur->addr); | |||
1674 | int err = uv_inet_ntop(cur->family, caddr, ip, sizeof(ip)); | |||
1675 | CHECK_EQ(err, 0)do { if (__builtin_expect(!!(!((err) == (0))), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1675", "(err) == (0)", __PRETTY_FUNCTION__ }; node::Assert( args); } while (0); } } while (0); | |||
1676 | ||||
1677 | Local<Value> ret[] = { | |||
1678 | OneByteString(env->isolate(), ip), | |||
1679 | Integer::New(env->isolate(), cur->udp_port) | |||
1680 | }; | |||
1681 | ||||
1682 | if (server_array->Set(env->context(), i, | |||
1683 | Array::New(env->isolate(), ret, arraysize(ret))) | |||
1684 | .IsNothing()) { | |||
1685 | return; | |||
1686 | } | |||
1687 | } | |||
1688 | ||||
1689 | args.GetReturnValue().Set(server_array); | |||
1690 | } | |||
1691 | ||||
1692 | ||||
1693 | void SetServers(const FunctionCallbackInfo<Value>& args) { | |||
1694 | Environment* env = Environment::GetCurrent(args); | |||
1695 | ChannelWrap* channel; | |||
1696 | ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder())do { *&channel = static_cast<typename std::remove_reference <decltype(*&channel)>::type>( BaseObject::FromJSObject (args.Holder())); if (*&channel == nullptr) return ; } while (0); | |||
1697 | ||||
1698 | if (channel->active_query_count()) { | |||
1699 | return args.GetReturnValue().Set(DNS_ESETSRVPENDING); | |||
1700 | } | |||
1701 | ||||
1702 | CHECK(args[0]->IsArray())do { if (__builtin_expect(!!(!(args[0]->IsArray())), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1702", "args[0]->IsArray()", __PRETTY_FUNCTION__ }; node ::Assert(args); } while (0); } } while (0); | |||
1703 | ||||
1704 | Local<Array> arr = args[0].As<Array>(); | |||
1705 | ||||
1706 | uint32_t len = arr->Length(); | |||
1707 | ||||
1708 | if (len == 0) { | |||
1709 | int rv = ares_set_servers(channel->cares_channel(), nullptr); | |||
1710 | return args.GetReturnValue().Set(rv); | |||
1711 | } | |||
1712 | ||||
1713 | std::vector<ares_addr_port_node> servers(len); | |||
1714 | ares_addr_port_node* last = nullptr; | |||
1715 | ||||
1716 | int err; | |||
1717 | ||||
1718 | for (uint32_t i = 0; i < len; i++) { | |||
1719 | CHECK(arr->Get(env->context(), i).ToLocalChecked()->IsArray())do { if (__builtin_expect(!!(!(arr->Get(env->context(), i).ToLocalChecked()->IsArray())), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1719" , "arr->Get(env->context(), i).ToLocalChecked()->IsArray()" , __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
1720 | ||||
1721 | Local<Array> elm = arr->Get(env->context(), i).ToLocalChecked().As<Array>(); | |||
1722 | ||||
1723 | CHECK(elm->Get(env->context(),do { if (__builtin_expect(!!(!(elm->Get(env->context(), 0).ToLocalChecked()->Int32Value(env->context()).FromJust ())), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1724", "elm->Get(env->context(), 0).ToLocalChecked()->Int32Value(env->context()).FromJust()" , __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0) | |||
1724 | 0).ToLocalChecked()->Int32Value(env->context()).FromJust())do { if (__builtin_expect(!!(!(elm->Get(env->context(), 0).ToLocalChecked()->Int32Value(env->context()).FromJust ())), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1724", "elm->Get(env->context(), 0).ToLocalChecked()->Int32Value(env->context()).FromJust()" , __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
1725 | CHECK(elm->Get(env->context(), 1).ToLocalChecked()->IsString())do { if (__builtin_expect(!!(!(elm->Get(env->context(), 1).ToLocalChecked()->IsString())), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1725" , "elm->Get(env->context(), 1).ToLocalChecked()->IsString()" , __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
1726 | CHECK(elm->Get(env->context(),do { if (__builtin_expect(!!(!(elm->Get(env->context(), 2).ToLocalChecked()->Int32Value(env->context()).FromJust ())), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1727", "elm->Get(env->context(), 2).ToLocalChecked()->Int32Value(env->context()).FromJust()" , __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0) | |||
1727 | 2).ToLocalChecked()->Int32Value(env->context()).FromJust())do { if (__builtin_expect(!!(!(elm->Get(env->context(), 2).ToLocalChecked()->Int32Value(env->context()).FromJust ())), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1727", "elm->Get(env->context(), 2).ToLocalChecked()->Int32Value(env->context()).FromJust()" , __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
1728 | ||||
1729 | int fam = elm->Get(env->context(), 0) | |||
1730 | .ToLocalChecked()->Int32Value(env->context()).FromJust(); | |||
1731 | node::Utf8Value ip(env->isolate(), | |||
1732 | elm->Get(env->context(), 1).ToLocalChecked()); | |||
1733 | int port = elm->Get(env->context(), 2) | |||
1734 | .ToLocalChecked()->Int32Value(env->context()).FromJust(); | |||
1735 | ||||
1736 | ares_addr_port_node* cur = &servers[i]; | |||
1737 | ||||
1738 | cur->tcp_port = cur->udp_port = port; | |||
1739 | switch (fam) { | |||
1740 | case 4: | |||
1741 | cur->family = AF_INET2; | |||
1742 | err = uv_inet_pton(AF_INET2, *ip, &cur->addr); | |||
1743 | break; | |||
1744 | case 6: | |||
1745 | cur->family = AF_INET610; | |||
1746 | err = uv_inet_pton(AF_INET610, *ip, &cur->addr); | |||
1747 | break; | |||
1748 | default: | |||
1749 | CHECK(0 && "Bad address family.")do { if (__builtin_expect(!!(!(0 && "Bad address family." )), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1749", "0 && \"Bad address family.\"", __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
1750 | } | |||
1751 | ||||
1752 | if (err) | |||
1753 | break; | |||
1754 | ||||
1755 | cur->next = nullptr; | |||
1756 | ||||
1757 | if (last != nullptr) | |||
1758 | last->next = cur; | |||
1759 | ||||
1760 | last = cur; | |||
1761 | } | |||
1762 | ||||
1763 | if (err == 0) | |||
1764 | err = ares_set_servers_ports(channel->cares_channel(), &servers[0]); | |||
1765 | else | |||
1766 | err = ARES_EBADSTR17; | |||
1767 | ||||
1768 | if (err == ARES_SUCCESS0) | |||
1769 | channel->set_is_servers_default(false); | |||
1770 | ||||
1771 | args.GetReturnValue().Set(err); | |||
1772 | } | |||
1773 | ||||
1774 | void SetLocalAddress(const FunctionCallbackInfo<Value>& args) { | |||
1775 | Environment* env = Environment::GetCurrent(args); | |||
1776 | ChannelWrap* channel; | |||
1777 | ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder())do { *&channel = static_cast<typename std::remove_reference <decltype(*&channel)>::type>( BaseObject::FromJSObject (args.Holder())); if (*&channel == nullptr) return ; } while (0); | |||
1778 | ||||
1779 | CHECK_EQ(args.Length(), 2)do { if (__builtin_expect(!!(!((args.Length()) == (2))), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1779", "(args.Length()) == (2)", __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
1780 | CHECK(args[0]->IsString())do { if (__builtin_expect(!!(!(args[0]->IsString())), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1780", "args[0]->IsString()", __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
1781 | ||||
1782 | Isolate* isolate = args.GetIsolate(); | |||
1783 | node::Utf8Value ip0(isolate, args[0]); | |||
1784 | ||||
1785 | unsigned char addr0[sizeof(struct in6_addr)]; | |||
1786 | unsigned char addr1[sizeof(struct in6_addr)]; | |||
1787 | int type0 = 0; | |||
1788 | ||||
1789 | // This function accepts 2 arguments. The first may be either an IPv4 | |||
1790 | // address or an IPv6 address. If present, the second argument must be the | |||
1791 | // other type of address. Otherwise, the unspecified type of IP is set | |||
1792 | // to 0 (any). | |||
1793 | ||||
1794 | if (uv_inet_pton(AF_INET2, *ip0, &addr0) == 0) { | |||
1795 | ares_set_local_ip4(channel->cares_channel(), ReadUint32BE(addr0)); | |||
1796 | type0 = 4; | |||
1797 | } else if (uv_inet_pton(AF_INET610, *ip0, &addr0) == 0) { | |||
1798 | ares_set_local_ip6(channel->cares_channel(), addr0); | |||
1799 | type0 = 6; | |||
1800 | } else { | |||
1801 | THROW_ERR_INVALID_ARG_VALUE(env, "Invalid IP address."); | |||
1802 | return; | |||
1803 | } | |||
1804 | ||||
1805 | if (!args[1]->IsUndefined()) { | |||
1806 | CHECK(args[1]->IsString())do { if (__builtin_expect(!!(!(args[1]->IsString())), 0)) { do { static const node::AssertionInfo args = { "../src/cares_wrap.cc" ":" "1806", "args[1]->IsString()", __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
1807 | node::Utf8Value ip1(isolate, args[1]); | |||
1808 | ||||
1809 | if (uv_inet_pton(AF_INET2, *ip1, &addr1) == 0) { | |||
1810 | if (type0 == 4) { | |||
1811 | THROW_ERR_INVALID_ARG_VALUE(env, "Cannot specify two IPv4 addresses."); | |||
1812 | return; | |||
1813 | } else { | |||
1814 | ares_set_local_ip4(channel->cares_channel(), ReadUint32BE(addr1)); | |||
1815 | } | |||
1816 | } else if (uv_inet_pton(AF_INET610, *ip1, &addr1) == 0) { | |||
1817 | if (type0 == 6) { | |||
1818 | THROW_ERR_INVALID_ARG_VALUE(env, "Cannot specify two IPv6 addresses."); | |||
1819 | return; | |||
1820 | } else { | |||
1821 | ares_set_local_ip6(channel->cares_channel(), addr1); | |||
1822 | } | |||
1823 | } else { | |||
1824 | THROW_ERR_INVALID_ARG_VALUE(env, "Invalid IP address."); | |||
1825 | return; | |||
1826 | } | |||
1827 | } else { | |||
1828 | // No second arg specified | |||
1829 | if (type0 == 4) { | |||
1830 | memset(&addr1, 0, sizeof(addr1)); | |||
1831 | ares_set_local_ip6(channel->cares_channel(), addr1); | |||
1832 | } else { | |||
1833 | ares_set_local_ip4(channel->cares_channel(), 0); | |||
1834 | } | |||
1835 | } | |||
1836 | } | |||
1837 | ||||
1838 | void Cancel(const FunctionCallbackInfo<Value>& args) { | |||
1839 | ChannelWrap* channel; | |||
1840 | ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder())do { *&channel = static_cast<typename std::remove_reference <decltype(*&channel)>::type>( BaseObject::FromJSObject (args.Holder())); if (*&channel == nullptr) return ; } while (0); | |||
1841 | ||||
1842 | TRACE_EVENT_INSTANT0(TRACING_CATEGORY_NODE2(dns, native),do { static std::atomic<intptr_t> trace_event_unique_atomic1843 {0}; const uint8_t* trace_event_unique_category_group_enabled1843 ; trace_event_unique_category_group_enabled1843 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic1843).load() ); if (!trace_event_unique_category_group_enabled1843) { trace_event_unique_category_group_enabled1843 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "dns" "," "node" "." "dns" "." "native"); (trace_event_unique_atomic1843 ).store(reinterpret_cast<intptr_t>( trace_event_unique_category_group_enabled1843 )); };; if (*trace_event_unique_category_group_enabled1843 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags )) { node::tracing::AddTraceEvent( ('I'), trace_event_unique_category_group_enabled1843 , "cancel", node::tracing::kGlobalScope, node::tracing::kNoId , node::tracing::kNoId, (static_cast<unsigned int>(0)) | (static_cast<unsigned char>(2 << 3))); } } while (0) | |||
1843 | "cancel", TRACE_EVENT_SCOPE_THREAD)do { static std::atomic<intptr_t> trace_event_unique_atomic1843 {0}; const uint8_t* trace_event_unique_category_group_enabled1843 ; trace_event_unique_category_group_enabled1843 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic1843).load() ); if (!trace_event_unique_category_group_enabled1843) { trace_event_unique_category_group_enabled1843 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "dns" "," "node" "." "dns" "." "native"); (trace_event_unique_atomic1843 ).store(reinterpret_cast<intptr_t>( trace_event_unique_category_group_enabled1843 )); };; if (*trace_event_unique_category_group_enabled1843 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags )) { node::tracing::AddTraceEvent( ('I'), trace_event_unique_category_group_enabled1843 , "cancel", node::tracing::kGlobalScope, node::tracing::kNoId , node::tracing::kNoId, (static_cast<unsigned int>(0)) | (static_cast<unsigned char>(2 << 3))); } } while (0); | |||
1844 | ||||
1845 | ares_cancel(channel->cares_channel()); | |||
1846 | } | |||
1847 | ||||
1848 | const char EMSG_ESETSRVPENDING[] = "There are pending queries."; | |||
1849 | void StrError(const FunctionCallbackInfo<Value>& args) { | |||
1850 | Environment* env = Environment::GetCurrent(args); | |||
1851 | int code = args[0]->Int32Value(env->context()).FromJust(); | |||
1852 | const char* errmsg = (code == DNS_ESETSRVPENDING) ? | |||
1853 | EMSG_ESETSRVPENDING : | |||
1854 | ares_strerror(code); | |||
1855 | args.GetReturnValue().Set(OneByteString(env->isolate(), errmsg)); | |||
1856 | } | |||
1857 | ||||
1858 | } // namespace | |||
1859 | ||||
1860 | inline void safe_free_hostent(struct hostent* host) { | |||
1861 | int idx; | |||
1862 | ||||
1863 | if (host->h_addr_list != nullptr) { | |||
1864 | idx = 0; | |||
1865 | while (host->h_addr_list[idx]) { | |||
1866 | free(host->h_addr_list[idx++]); | |||
1867 | } | |||
1868 | free(host->h_addr_list); | |||
1869 | host->h_addr_list = nullptr; | |||
1870 | } | |||
1871 | ||||
1872 | if (host->h_aliases != nullptr) { | |||
1873 | idx = 0; | |||
1874 | while (host->h_aliases[idx]) { | |||
1875 | free(host->h_aliases[idx++]); | |||
1876 | } | |||
1877 | free(host->h_aliases); | |||
1878 | host->h_aliases = nullptr; | |||
1879 | } | |||
1880 | ||||
1881 | free(host->h_name); | |||
1882 | free(host); | |||
1883 | } | |||
1884 | ||||
1885 | void Initialize(Local<Object> target, | |||
1886 | Local<Value> unused, | |||
1887 | Local<Context> context, | |||
1888 | void* priv) { | |||
1889 | Environment* env = Environment::GetCurrent(context); | |||
1890 | ||||
1891 | env->SetMethod(target, "getaddrinfo", GetAddrInfo); | |||
1892 | env->SetMethod(target, "getnameinfo", GetNameInfo); | |||
1893 | env->SetMethodNoSideEffect(target, "canonicalizeIP", CanonicalizeIP); | |||
1894 | ||||
1895 | env->SetMethod(target, "strerror", StrError); | |||
1896 | ||||
1897 | target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET"), | |||
1898 | Integer::New(env->isolate(), AF_INET2)).Check(); | |||
1899 | target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET6"), | |||
1900 | Integer::New(env->isolate(), AF_INET610)).Check(); | |||
1901 | target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), | |||
1902 | "AF_UNSPEC"), | |||
1903 | Integer::New(env->isolate(), AF_UNSPEC0)).Check(); | |||
1904 | target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), | |||
1905 | "AI_ADDRCONFIG"), | |||
1906 | Integer::New(env->isolate(), AI_ADDRCONFIG0x0020)).Check(); | |||
1907 | target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), | |||
1908 | "AI_ALL"), | |||
1909 | Integer::New(env->isolate(), AI_ALL0x0010)).Check(); | |||
1910 | target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), | |||
1911 | "AI_V4MAPPED"), | |||
1912 | Integer::New(env->isolate(), AI_V4MAPPED0x0008)).Check(); | |||
1913 | ||||
1914 | Local<FunctionTemplate> aiw = | |||
1915 | BaseObject::MakeLazilyInitializedJSTemplate(env); | |||
1916 | aiw->Inherit(AsyncWrap::GetConstructorTemplate(env)); | |||
1917 | env->SetConstructorFunction(target, "GetAddrInfoReqWrap", aiw); | |||
1918 | ||||
1919 | Local<FunctionTemplate> niw = | |||
1920 | BaseObject::MakeLazilyInitializedJSTemplate(env); | |||
1921 | niw->Inherit(AsyncWrap::GetConstructorTemplate(env)); | |||
1922 | env->SetConstructorFunction(target, "GetNameInfoReqWrap", niw); | |||
1923 | ||||
1924 | Local<FunctionTemplate> qrw = | |||
1925 | BaseObject::MakeLazilyInitializedJSTemplate(env); | |||
1926 | qrw->Inherit(AsyncWrap::GetConstructorTemplate(env)); | |||
1927 | env->SetConstructorFunction(target, "QueryReqWrap", qrw); | |||
1928 | ||||
1929 | Local<FunctionTemplate> channel_wrap = | |||
1930 | env->NewFunctionTemplate(ChannelWrap::New); | |||
1931 | channel_wrap->InstanceTemplate()->SetInternalFieldCount( | |||
1932 | ChannelWrap::kInternalFieldCount); | |||
1933 | channel_wrap->Inherit(AsyncWrap::GetConstructorTemplate(env)); | |||
1934 | ||||
1935 | env->SetProtoMethod(channel_wrap, "queryAny", Query<QueryAnyWrap>); | |||
1936 | env->SetProtoMethod(channel_wrap, "queryA", Query<QueryAWrap>); | |||
1937 | env->SetProtoMethod(channel_wrap, "queryAaaa", Query<QueryAaaaWrap>); | |||
1938 | env->SetProtoMethod(channel_wrap, "queryCaa", Query<QueryCaaWrap>); | |||
1939 | env->SetProtoMethod(channel_wrap, "queryCname", Query<QueryCnameWrap>); | |||
1940 | env->SetProtoMethod(channel_wrap, "queryMx", Query<QueryMxWrap>); | |||
1941 | env->SetProtoMethod(channel_wrap, "queryNs", Query<QueryNsWrap>); | |||
1942 | env->SetProtoMethod(channel_wrap, "queryTxt", Query<QueryTxtWrap>); | |||
1943 | env->SetProtoMethod(channel_wrap, "querySrv", Query<QuerySrvWrap>); | |||
1944 | env->SetProtoMethod(channel_wrap, "queryPtr", Query<QueryPtrWrap>); | |||
1945 | env->SetProtoMethod(channel_wrap, "queryNaptr", Query<QueryNaptrWrap>); | |||
1946 | env->SetProtoMethod(channel_wrap, "querySoa", Query<QuerySoaWrap>); | |||
1947 | env->SetProtoMethod(channel_wrap, "getHostByAddr", Query<GetHostByAddrWrap>); | |||
1948 | ||||
1949 | env->SetProtoMethodNoSideEffect(channel_wrap, "getServers", GetServers); | |||
1950 | env->SetProtoMethod(channel_wrap, "setServers", SetServers); | |||
1951 | env->SetProtoMethod(channel_wrap, "setLocalAddress", SetLocalAddress); | |||
1952 | env->SetProtoMethod(channel_wrap, "cancel", Cancel); | |||
1953 | ||||
1954 | env->SetConstructorFunction(target, "ChannelWrap", channel_wrap); | |||
1955 | } | |||
1956 | ||||
1957 | } // namespace cares_wrap | |||
1958 | } // namespace node | |||
1959 | ||||
1960 | NODE_MODULE_CONTEXT_AWARE_INTERNAL(cares_wrap, node::cares_wrap::Initialize)static node::node_module _module = { 108, NM_F_INTERNAL, nullptr , "../src/cares_wrap.cc", nullptr, (node::addon_context_register_func )(node::cares_wrap::Initialize), "cares_wrap", nullptr, nullptr }; void _register_cares_wrap() { node_module_register(&_module ); } |
1 | #ifndef SRC_MEMORY_TRACKER_INL_H_ | |||
2 | #define SRC_MEMORY_TRACKER_INL_H_ | |||
3 | ||||
4 | #if defined(NODE_WANT_INTERNALS1) && NODE_WANT_INTERNALS1 | |||
5 | ||||
6 | #include "memory_tracker.h" | |||
7 | ||||
8 | namespace node { | |||
9 | ||||
10 | // Fallback edge_name if node_name is not available, or "" if edge_name | |||
11 | // is not available either. | |||
12 | inline const char* GetNodeName(const char* node_name, const char* edge_name) { | |||
13 | if (node_name != nullptr) { | |||
14 | return node_name; | |||
15 | } | |||
16 | if (edge_name != nullptr) { | |||
17 | return edge_name; | |||
18 | } | |||
19 | return ""; | |||
20 | } | |||
21 | ||||
22 | class MemoryRetainerNode : public v8::EmbedderGraph::Node { | |||
23 | public: | |||
24 | inline MemoryRetainerNode(MemoryTracker* tracker, | |||
25 | const MemoryRetainer* retainer) | |||
26 | : retainer_(retainer) { | |||
27 | CHECK_NOT_NULL(retainer_)do { if (__builtin_expect(!!(!((retainer_) != nullptr)), 0)) { do { static const node::AssertionInfo args = { "../src/memory_tracker-inl.h" ":" "27", "(retainer_) != nullptr", __PRETTY_FUNCTION__ }; node ::Assert(args); } while (0); } } while (0); | |||
28 | v8::HandleScope handle_scope(tracker->isolate()); | |||
29 | v8::Local<v8::Object> obj = retainer_->WrappedObject(); | |||
30 | if (!obj.IsEmpty()) wrapper_node_ = tracker->graph()->V8Node(obj); | |||
31 | ||||
32 | name_ = retainer_->MemoryInfoName(); | |||
33 | size_ = retainer_->SelfSize(); | |||
34 | } | |||
35 | ||||
36 | inline MemoryRetainerNode(MemoryTracker* tracker, | |||
37 | const char* name, | |||
38 | size_t size, | |||
39 | bool is_root_node = false) | |||
40 | : retainer_(nullptr) { | |||
41 | name_ = name; | |||
42 | size_ = size; | |||
43 | is_root_node_ = is_root_node; | |||
44 | } | |||
45 | ||||
46 | const char* Name() override { return name_.c_str(); } | |||
47 | const char* NamePrefix() override { return "Node /"; } | |||
48 | size_t SizeInBytes() override { return size_; } | |||
49 | // TODO(addaleax): Merging this with the "official" WrapperNode() method | |||
50 | // seems to lose accuracy, e.g. SizeInBytes() is disregarded. | |||
51 | // Figure out whether to do anything about that. | |||
52 | Node* JSWrapperNode() { return wrapper_node_; } | |||
53 | ||||
54 | bool IsRootNode() override { | |||
55 | if (retainer_ != nullptr) { | |||
56 | return retainer_->IsRootNode(); | |||
57 | } | |||
58 | return is_root_node_; | |||
59 | } | |||
60 | ||||
61 | private: | |||
62 | friend class MemoryTracker; | |||
63 | ||||
64 | // If retainer_ is not nullptr, then it must have a wrapper_node_, | |||
65 | // and we have | |||
66 | // name_ == retainer_->MemoryInfoName() | |||
67 | // size_ == retainer_->SelfSize() | |||
68 | // is_root_node_ == retainer_->IsRootNode() | |||
69 | const MemoryRetainer* retainer_; | |||
70 | Node* wrapper_node_ = nullptr; | |||
71 | ||||
72 | // Otherwise (retainer == nullptr), we set these fields in an ad-hoc way | |||
73 | bool is_root_node_ = false; | |||
74 | std::string name_; | |||
75 | size_t size_ = 0; | |||
76 | }; | |||
77 | ||||
78 | void MemoryTracker::TrackFieldWithSize(const char* edge_name, | |||
79 | size_t size, | |||
80 | const char* node_name) { | |||
81 | if (size > 0) AddNode(GetNodeName(node_name, edge_name), size, edge_name); | |||
82 | } | |||
83 | ||||
84 | void MemoryTracker::TrackInlineFieldWithSize(const char* edge_name, | |||
85 | size_t size, | |||
86 | const char* node_name) { | |||
87 | if (size > 0) AddNode(GetNodeName(node_name, edge_name), size, edge_name); | |||
88 | CHECK(CurrentNode())do { if (__builtin_expect(!!(!(CurrentNode())), 0)) { do { static const node::AssertionInfo args = { "../src/memory_tracker-inl.h" ":" "88", "CurrentNode()", __PRETTY_FUNCTION__ }; node::Assert (args); } while (0); } } while (0); | |||
89 | CurrentNode()->size_ -= size; | |||
90 | } | |||
91 | ||||
92 | void MemoryTracker::TrackField(const char* edge_name, | |||
93 | const MemoryRetainer& value, | |||
94 | const char* node_name) { | |||
95 | TrackField(edge_name, &value); | |||
96 | } | |||
97 | ||||
98 | void MemoryTracker::TrackField(const char* edge_name, | |||
99 | const MemoryRetainer* value, | |||
100 | const char* node_name) { | |||
101 | if (value == nullptr) return; | |||
102 | auto it = seen_.find(value); | |||
103 | if (it != seen_.end()) { | |||
104 | graph_->AddEdge(CurrentNode(), it->second, edge_name); | |||
105 | } else { | |||
106 | Track(value, edge_name); | |||
107 | } | |||
108 | } | |||
109 | ||||
110 | template <typename T, typename D> | |||
111 | void MemoryTracker::TrackField(const char* edge_name, | |||
112 | const std::unique_ptr<T, D>& value, | |||
113 | const char* node_name) { | |||
114 | if (value.get() == nullptr) { | |||
115 | return; | |||
116 | } | |||
117 | TrackField(edge_name, value.get(), node_name); | |||
118 | } | |||
119 | ||||
120 | template <typename T> | |||
121 | void MemoryTracker::TrackField(const char* edge_name, | |||
122 | const std::shared_ptr<T>& value, | |||
123 | const char* node_name) { | |||
124 | if (value.get() == nullptr) { | |||
125 | return; | |||
126 | } | |||
127 | TrackField(edge_name, value.get(), node_name); | |||
128 | } | |||
129 | ||||
130 | template <typename T, bool kIsWeak> | |||
131 | void MemoryTracker::TrackField(const char* edge_name, | |||
132 | const BaseObjectPtrImpl<T, kIsWeak>& value, | |||
133 | const char* node_name) { | |||
134 | if (value.get() == nullptr || kIsWeak) return; | |||
135 | TrackField(edge_name, value.get(), node_name); | |||
136 | } | |||
137 | ||||
138 | template <typename T, typename Iterator> | |||
139 | void MemoryTracker::TrackField(const char* edge_name, | |||
140 | const T& value, | |||
141 | const char* node_name, | |||
142 | const char* element_name, | |||
143 | bool subtract_from_self) { | |||
144 | // If the container is empty, the size has been accounted into the parent's | |||
145 | // self size | |||
146 | if (value.begin() == value.end()) return; | |||
147 | // Fall back to edge name if node names are not provided | |||
148 | if (CurrentNode() != nullptr && subtract_from_self) { | |||
149 | // Shift the self size of this container out to a separate node | |||
150 | CurrentNode()->size_ -= sizeof(T); | |||
151 | } | |||
152 | PushNode(GetNodeName(node_name, edge_name), sizeof(T), edge_name); | |||
153 | for (Iterator it = value.begin(); it != value.end(); ++it) { | |||
154 | // Use nullptr as edge names so the elements appear as indexed properties | |||
155 | TrackField(nullptr, *it, element_name); | |||
156 | } | |||
157 | PopNode(); | |||
158 | } | |||
159 | ||||
160 | template <typename T> | |||
161 | void MemoryTracker::TrackField(const char* edge_name, | |||
162 | const std::queue<T>& value, | |||
163 | const char* node_name, | |||
164 | const char* element_name) { | |||
165 | struct ContainerGetter : public std::queue<T> { | |||
166 | static const typename std::queue<T>::container_type& Get( | |||
167 | const std::queue<T>& value) { | |||
168 | return value.*&ContainerGetter::c; | |||
169 | } | |||
170 | }; | |||
171 | ||||
172 | const auto& container = ContainerGetter::Get(value); | |||
173 | TrackField(edge_name, container, node_name, element_name); | |||
174 | } | |||
175 | ||||
176 | template <typename T, typename test_for_number, typename dummy> | |||
177 | void MemoryTracker::TrackField(const char* edge_name, | |||
178 | const T& value, | |||
179 | const char* node_name) { | |||
180 | // For numbers, creating new nodes is not worth the overhead. | |||
181 | CurrentNode()->size_ += sizeof(T); | |||
182 | } | |||
183 | ||||
184 | template <typename T, typename U> | |||
185 | void MemoryTracker::TrackField(const char* edge_name, | |||
186 | const std::pair<T, U>& value, | |||
187 | const char* node_name) { | |||
188 | PushNode(node_name == nullptr ? "pair" : node_name, | |||
189 | sizeof(const std::pair<T, U>), | |||
190 | edge_name); | |||
191 | // TODO(joyeecheung): special case if one of these is a number type | |||
192 | // that meets the test_for_number trait so that their sizes don't get | |||
193 | // merged into the pair node | |||
194 | TrackField("first", value.first); | |||
195 | TrackField("second", value.second); | |||
196 | PopNode(); | |||
197 | } | |||
198 | ||||
199 | template <typename T> | |||
200 | void MemoryTracker::TrackField(const char* edge_name, | |||
201 | const std::basic_string<T>& value, | |||
202 | const char* node_name) { | |||
203 | TrackFieldWithSize(edge_name, value.size() * sizeof(T), "std::basic_string"); | |||
204 | } | |||
205 | ||||
206 | template <typename T> | |||
207 | void MemoryTracker::TrackField(const char* edge_name, | |||
208 | const v8::Eternal<T>& value, | |||
209 | const char* node_name) { | |||
210 | TrackField(edge_name, value.Get(isolate_)); | |||
211 | } | |||
212 | ||||
213 | template <typename T> | |||
214 | void MemoryTracker::TrackField(const char* edge_name, | |||
215 | const v8::PersistentBase<T>& value, | |||
216 | const char* node_name) { | |||
217 | if (value.IsWeak()) return; | |||
218 | TrackField(edge_name, value.Get(isolate_)); | |||
219 | } | |||
220 | ||||
221 | template <typename T> | |||
222 | void MemoryTracker::TrackField(const char* edge_name, | |||
223 | const v8::Local<T>& value, | |||
224 | const char* node_name) { | |||
225 | if (!value.IsEmpty()) | |||
226 | graph_->AddEdge(CurrentNode(), graph_->V8Node(value), edge_name); | |||
227 | } | |||
228 | ||||
229 | template <typename T> | |||
230 | void MemoryTracker::TrackField(const char* edge_name, | |||
231 | const MallocedBuffer<T>& value, | |||
232 | const char* node_name) { | |||
233 | TrackFieldWithSize(edge_name, value.size, "MallocedBuffer"); | |||
234 | } | |||
235 | ||||
236 | void MemoryTracker::TrackField(const char* edge_name, | |||
237 | const v8::BackingStore* value, | |||
238 | const char* node_name) { | |||
239 | TrackFieldWithSize(edge_name, value->ByteLength(), "BackingStore"); | |||
240 | } | |||
241 | ||||
242 | void MemoryTracker::TrackField(const char* name, | |||
243 | const uv_buf_t& value, | |||
244 | const char* node_name) { | |||
245 | TrackFieldWithSize(name, value.len, "uv_buf_t"); | |||
246 | } | |||
247 | ||||
248 | void MemoryTracker::TrackField(const char* name, | |||
249 | const uv_timer_t& value, | |||
250 | const char* node_name) { | |||
251 | TrackFieldWithSize(name, sizeof(value), "uv_timer_t"); | |||
252 | } | |||
253 | ||||
254 | void MemoryTracker::TrackField(const char* name, | |||
255 | const uv_async_t& value, | |||
256 | const char* node_name) { | |||
257 | TrackFieldWithSize(name, sizeof(value), "uv_async_t"); | |||
258 | } | |||
259 | ||||
260 | void MemoryTracker::TrackInlineField(const char* name, | |||
261 | const uv_async_t& value, | |||
262 | const char* node_name) { | |||
263 | TrackInlineFieldWithSize(name, sizeof(value), "uv_async_t"); | |||
264 | } | |||
265 | ||||
266 | template <class NativeT, class V8T> | |||
267 | void MemoryTracker::TrackField(const char* name, | |||
268 | const AliasedBufferBase<NativeT, V8T>& value, | |||
269 | const char* node_name) { | |||
270 | TrackField(name, value.GetJSArray(), "AliasedBuffer"); | |||
271 | } | |||
272 | ||||
273 | void MemoryTracker::Track(const MemoryRetainer* retainer, | |||
274 | const char* edge_name) { | |||
275 | v8::HandleScope handle_scope(isolate_); | |||
276 | auto it = seen_.find(retainer); | |||
277 | if (it != seen_.end()) { | |||
278 | if (CurrentNode() != nullptr) { | |||
279 | graph_->AddEdge(CurrentNode(), it->second, edge_name); | |||
280 | } | |||
281 | return; // It has already been tracked, no need to call MemoryInfo again | |||
282 | } | |||
283 | MemoryRetainerNode* n = PushNode(retainer, edge_name); | |||
284 | retainer->MemoryInfo(this); | |||
285 | CHECK_EQ(CurrentNode(), n)do { if (__builtin_expect(!!(!((CurrentNode()) == (n))), 0)) { do { static const node::AssertionInfo args = { "../src/memory_tracker-inl.h" ":" "285", "(CurrentNode()) == (n)", __PRETTY_FUNCTION__ }; node ::Assert(args); } while (0); } } while (0); | |||
286 | CHECK_NE(n->size_, 0)do { if (__builtin_expect(!!(!((n->size_) != (0))), 0)) { do { static const node::AssertionInfo args = { "../src/memory_tracker-inl.h" ":" "286", "(n->size_) != (0)", __PRETTY_FUNCTION__ }; node ::Assert(args); } while (0); } } while (0); | |||
| ||||
287 | PopNode(); | |||
288 | } | |||
289 | ||||
290 | void MemoryTracker::TrackInlineField(const MemoryRetainer* retainer, | |||
291 | const char* edge_name) { | |||
292 | Track(retainer, edge_name); | |||
293 | CHECK(CurrentNode())do { if (__builtin_expect(!!(!(CurrentNode())), 0)) { do { static const node::AssertionInfo args = { "../src/memory_tracker-inl.h" ":" "293", "CurrentNode()", __PRETTY_FUNCTION__ }; node::Assert (args); } while (0); } } while (0); | |||
294 | CurrentNode()->size_ -= retainer->SelfSize(); | |||
295 | } | |||
296 | ||||
297 | MemoryRetainerNode* MemoryTracker::CurrentNode() const { | |||
298 | if (node_stack_.empty()) return nullptr; | |||
299 | return node_stack_.top(); | |||
300 | } | |||
301 | ||||
302 | MemoryRetainerNode* MemoryTracker::AddNode(const MemoryRetainer* retainer, | |||
303 | const char* edge_name) { | |||
304 | auto it = seen_.find(retainer); | |||
305 | if (it != seen_.end()) { | |||
306 | return it->second; | |||
307 | } | |||
308 | ||||
309 | MemoryRetainerNode* n = new MemoryRetainerNode(this, retainer); | |||
310 | graph_->AddNode(std::unique_ptr<v8::EmbedderGraph::Node>(n)); | |||
311 | seen_[retainer] = n; | |||
312 | if (CurrentNode() != nullptr) graph_->AddEdge(CurrentNode(), n, edge_name); | |||
313 | ||||
314 | if (n->JSWrapperNode() != nullptr) { | |||
315 | graph_->AddEdge(n, n->JSWrapperNode(), "wrapped"); | |||
316 | graph_->AddEdge(n->JSWrapperNode(), n, "wrapper"); | |||
317 | } | |||
318 | ||||
319 | return n; | |||
320 | } | |||
321 | ||||
322 | MemoryRetainerNode* MemoryTracker::AddNode(const char* node_name, | |||
323 | size_t size, | |||
324 | const char* edge_name) { | |||
325 | MemoryRetainerNode* n = new MemoryRetainerNode(this, node_name, size); | |||
326 | graph_->AddNode(std::unique_ptr<v8::EmbedderGraph::Node>(n)); | |||
327 | ||||
328 | if (CurrentNode() != nullptr) graph_->AddEdge(CurrentNode(), n, edge_name); | |||
329 | ||||
330 | return n; | |||
331 | } | |||
332 | ||||
333 | MemoryRetainerNode* MemoryTracker::PushNode(const MemoryRetainer* retainer, | |||
334 | const char* edge_name) { | |||
335 | MemoryRetainerNode* n = AddNode(retainer, edge_name); | |||
336 | node_stack_.push(n); | |||
337 | return n; | |||
338 | } | |||
339 | ||||
340 | MemoryRetainerNode* MemoryTracker::PushNode(const char* node_name, | |||
341 | size_t size, | |||
342 | const char* edge_name) { | |||
343 | MemoryRetainerNode* n = AddNode(node_name, size, edge_name); | |||
344 | node_stack_.push(n); | |||
345 | return n; | |||
346 | } | |||
347 | ||||
348 | void MemoryTracker::PopNode() { | |||
349 | node_stack_.pop(); | |||
350 | } | |||
351 | ||||
352 | } // namespace node | |||
353 | ||||
354 | #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS | |||
355 | ||||
356 | #endif // SRC_MEMORY_TRACKER_INL_H_ |
1 | // Stack implementation -*- C++ -*- |
2 | |
3 | // Copyright (C) 2001-2018 Free Software Foundation, Inc. |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free |
6 | // software; you can redistribute it and/or modify it under the |
7 | // terms of the GNU General Public License as published by the |
8 | // Free Software Foundation; either version 3, or (at your option) |
9 | // any later version. |
10 | |
11 | // This library is distributed in the hope that it will be useful, |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | // GNU General Public License for more details. |
15 | |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version |
18 | // 3.1, as published by the Free Software Foundation. |
19 | |
20 | // You should have received a copy of the GNU General Public License and |
21 | // a copy of the GCC Runtime Library Exception along with this program; |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
23 | // <http://www.gnu.org/licenses/>. |
24 | |
25 | /* |
26 | * |
27 | * Copyright (c) 1994 |
28 | * Hewlett-Packard Company |
29 | * |
30 | * Permission to use, copy, modify, distribute and sell this software |
31 | * and its documentation for any purpose is hereby granted without fee, |
32 | * provided that the above copyright notice appear in all copies and |
33 | * that both that copyright notice and this permission notice appear |
34 | * in supporting documentation. Hewlett-Packard Company makes no |
35 | * representations about the suitability of this software for any |
36 | * purpose. It is provided "as is" without express or implied warranty. |
37 | * |
38 | * |
39 | * Copyright (c) 1996,1997 |
40 | * Silicon Graphics Computer Systems, Inc. |
41 | * |
42 | * Permission to use, copy, modify, distribute and sell this software |
43 | * and its documentation for any purpose is hereby granted without fee, |
44 | * provided that the above copyright notice appear in all copies and |
45 | * that both that copyright notice and this permission notice appear |
46 | * in supporting documentation. Silicon Graphics makes no |
47 | * representations about the suitability of this software for any |
48 | * purpose. It is provided "as is" without express or implied warranty. |
49 | */ |
50 | |
51 | /** @file bits/stl_stack.h |
52 | * This is an internal header file, included by other library headers. |
53 | * Do not attempt to use it directly. @headername{stack} |
54 | */ |
55 | |
56 | #ifndef _STL_STACK_H1 |
57 | #define _STL_STACK_H1 1 |
58 | |
59 | #include <bits/concept_check.h> |
60 | #include <debug/debug.h> |
61 | #if __cplusplus201703L >= 201103L |
62 | # include <bits/uses_allocator.h> |
63 | #endif |
64 | |
65 | namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default"))) |
66 | { |
67 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
68 | |
69 | /** |
70 | * @brief A standard container giving FILO behavior. |
71 | * |
72 | * @ingroup sequences |
73 | * |
74 | * @tparam _Tp Type of element. |
75 | * @tparam _Sequence Type of underlying sequence, defaults to deque<_Tp>. |
76 | * |
77 | * Meets many of the requirements of a |
78 | * <a href="tables.html#65">container</a>, |
79 | * but does not define anything to do with iterators. Very few of the |
80 | * other standard container interfaces are defined. |
81 | * |
82 | * This is not a true container, but an @e adaptor. It holds |
83 | * another container, and provides a wrapper interface to that |
84 | * container. The wrapper is what enforces strict |
85 | * first-in-last-out %stack behavior. |
86 | * |
87 | * The second template parameter defines the type of the underlying |
88 | * sequence/container. It defaults to std::deque, but it can be |
89 | * any type that supports @c back, @c push_back, and @c pop_back, |
90 | * such as std::list, std::vector, or an appropriate user-defined |
91 | * type. |
92 | * |
93 | * Members not found in @a normal containers are @c container_type, |
94 | * which is a typedef for the second Sequence parameter, and @c |
95 | * push, @c pop, and @c top, which are standard %stack/FILO |
96 | * operations. |
97 | */ |
98 | template<typename _Tp, typename _Sequence = deque<_Tp> > |
99 | class stack |
100 | { |
101 | #ifdef _GLIBCXX_CONCEPT_CHECKS |
102 | // concept requirements |
103 | typedef typename _Sequence::value_type _Sequence_value_type; |
104 | # if __cplusplus201703L < 201103L |
105 | __glibcxx_class_requires(_Tp, _SGIAssignableConcept) |
106 | __glibcxx_class_requires(_Sequence, _BackInsertionSequenceConcept) |
107 | # endif |
108 | __glibcxx_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept) |
109 | #endif |
110 | |
111 | template<typename _Tp1, typename _Seq1> |
112 | friend bool |
113 | operator==(const stack<_Tp1, _Seq1>&, const stack<_Tp1, _Seq1>&); |
114 | |
115 | template<typename _Tp1, typename _Seq1> |
116 | friend bool |
117 | operator<(const stack<_Tp1, _Seq1>&, const stack<_Tp1, _Seq1>&); |
118 | |
119 | #if __cplusplus201703L >= 201103L |
120 | template<typename _Alloc> |
121 | using _Uses = typename |
122 | enable_if<uses_allocator<_Sequence, _Alloc>::value>::type; |
123 | #endif |
124 | |
125 | public: |
126 | typedef typename _Sequence::value_type value_type; |
127 | typedef typename _Sequence::reference reference; |
128 | typedef typename _Sequence::const_reference const_reference; |
129 | typedef typename _Sequence::size_type size_type; |
130 | typedef _Sequence container_type; |
131 | |
132 | protected: |
133 | // See queue::c for notes on this name. |
134 | _Sequence c; |
135 | |
136 | public: |
137 | // XXX removed old def ctor, added def arg to this one to match 14882 |
138 | /** |
139 | * @brief Default constructor creates no elements. |
140 | */ |
141 | #if __cplusplus201703L < 201103L |
142 | explicit |
143 | stack(const _Sequence& __c = _Sequence()) |
144 | : c(__c) { } |
145 | #else |
146 | template<typename _Seq = _Sequence, typename _Requires = typename |
147 | enable_if<is_default_constructible<_Seq>::value>::type> |
148 | stack() |
149 | : c() { } |
150 | |
151 | explicit |
152 | stack(const _Sequence& __c) |
153 | : c(__c) { } |
154 | |
155 | explicit |
156 | stack(_Sequence&& __c) |
157 | : c(std::move(__c)) { } |
158 | |
159 | template<typename _Alloc, typename _Requires = _Uses<_Alloc>> |
160 | explicit |
161 | stack(const _Alloc& __a) |
162 | : c(__a) { } |
163 | |
164 | template<typename _Alloc, typename _Requires = _Uses<_Alloc>> |
165 | stack(const _Sequence& __c, const _Alloc& __a) |
166 | : c(__c, __a) { } |
167 | |
168 | template<typename _Alloc, typename _Requires = _Uses<_Alloc>> |
169 | stack(_Sequence&& __c, const _Alloc& __a) |
170 | : c(std::move(__c), __a) { } |
171 | |
172 | template<typename _Alloc, typename _Requires = _Uses<_Alloc>> |
173 | stack(const stack& __q, const _Alloc& __a) |
174 | : c(__q.c, __a) { } |
175 | |
176 | template<typename _Alloc, typename _Requires = _Uses<_Alloc>> |
177 | stack(stack&& __q, const _Alloc& __a) |
178 | : c(std::move(__q.c), __a) { } |
179 | #endif |
180 | |
181 | /** |
182 | * Returns true if the %stack is empty. |
183 | */ |
184 | bool |
185 | empty() const |
186 | { return c.empty(); } |
187 | |
188 | /** Returns the number of elements in the %stack. */ |
189 | size_type |
190 | size() const |
191 | { return c.size(); } |
192 | |
193 | /** |
194 | * Returns a read/write reference to the data at the first |
195 | * element of the %stack. |
196 | */ |
197 | reference |
198 | top() |
199 | { |
200 | __glibcxx_requires_nonempty(); |
201 | return c.back(); |
202 | } |
203 | |
204 | /** |
205 | * Returns a read-only (constant) reference to the data at the first |
206 | * element of the %stack. |
207 | */ |
208 | const_reference |
209 | top() const |
210 | { |
211 | __glibcxx_requires_nonempty(); |
212 | return c.back(); |
213 | } |
214 | |
215 | /** |
216 | * @brief Add data to the top of the %stack. |
217 | * @param __x Data to be added. |
218 | * |
219 | * This is a typical %stack operation. The function creates an |
220 | * element at the top of the %stack and assigns the given data |
221 | * to it. The time complexity of the operation depends on the |
222 | * underlying sequence. |
223 | */ |
224 | void |
225 | push(const value_type& __x) |
226 | { c.push_back(__x); } |
227 | |
228 | #if __cplusplus201703L >= 201103L |
229 | void |
230 | push(value_type&& __x) |
231 | { c.push_back(std::move(__x)); } |
232 | |
233 | #if __cplusplus201703L > 201402L |
234 | template<typename... _Args> |
235 | decltype(auto) |
236 | emplace(_Args&&... __args) |
237 | { return c.emplace_back(std::forward<_Args>(__args)...); } |
238 | #else |
239 | template<typename... _Args> |
240 | void |
241 | emplace(_Args&&... __args) |
242 | { c.emplace_back(std::forward<_Args>(__args)...); } |
243 | #endif |
244 | #endif |
245 | |
246 | /** |
247 | * @brief Removes first element. |
248 | * |
249 | * This is a typical %stack operation. It shrinks the %stack |
250 | * by one. The time complexity of the operation depends on the |
251 | * underlying sequence. |
252 | * |
253 | * Note that no data is returned, and if the first element's |
254 | * data is needed, it should be retrieved before pop() is |
255 | * called. |
256 | */ |
257 | void |
258 | pop() |
259 | { |
260 | __glibcxx_requires_nonempty(); |
261 | c.pop_back(); |
262 | } |
263 | |
264 | #if __cplusplus201703L >= 201103L |
265 | void |
266 | swap(stack& __s) |
267 | #if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 |
268 | noexcept(__is_nothrow_swappable<_Sequence>::value) |
269 | #else |
270 | noexcept(__is_nothrow_swappable<_Tp>::value) |
271 | #endif |
272 | { |
273 | using std::swap; |
274 | swap(c, __s.c); |
275 | } |
276 | #endif // __cplusplus >= 201103L |
277 | }; |
278 | |
279 | #if __cpp_deduction_guides201703L >= 201606 |
280 | template<typename _Container, |
281 | typename = enable_if_t<!__is_allocator<_Container>::value>> |
282 | stack(_Container) -> stack<typename _Container::value_type, _Container>; |
283 | |
284 | template<typename _Container, typename _Allocator, |
285 | typename = enable_if_t<!__is_allocator<_Container>::value>, |
286 | typename = enable_if_t<__is_allocator<_Allocator>::value>> |
287 | stack(_Container, _Allocator) |
288 | -> stack<typename _Container::value_type, _Container>; |
289 | #endif |
290 | |
291 | /** |
292 | * @brief Stack equality comparison. |
293 | * @param __x A %stack. |
294 | * @param __y A %stack of the same type as @a __x. |
295 | * @return True iff the size and elements of the stacks are equal. |
296 | * |
297 | * This is an equivalence relation. Complexity and semantics |
298 | * depend on the underlying sequence type, but the expected rules |
299 | * are: this relation is linear in the size of the sequences, and |
300 | * stacks are considered equivalent if their sequences compare |
301 | * equal. |
302 | */ |
303 | template<typename _Tp, typename _Seq> |
304 | inline bool |
305 | operator==(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) |
306 | { return __x.c == __y.c; } |
307 | |
308 | /** |
309 | * @brief Stack ordering relation. |
310 | * @param __x A %stack. |
311 | * @param __y A %stack of the same type as @a x. |
312 | * @return True iff @a x is lexicographically less than @a __y. |
313 | * |
314 | * This is an total ordering relation. Complexity and semantics |
315 | * depend on the underlying sequence type, but the expected rules |
316 | * are: this relation is linear in the size of the sequences, the |
317 | * elements must be comparable with @c <, and |
318 | * std::lexicographical_compare() is usually used to make the |
319 | * determination. |
320 | */ |
321 | template<typename _Tp, typename _Seq> |
322 | inline bool |
323 | operator<(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) |
324 | { return __x.c < __y.c; } |
325 | |
326 | /// Based on operator== |
327 | template<typename _Tp, typename _Seq> |
328 | inline bool |
329 | operator!=(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) |
330 | { return !(__x == __y); } |
331 | |
332 | /// Based on operator< |
333 | template<typename _Tp, typename _Seq> |
334 | inline bool |
335 | operator>(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) |
336 | { return __y < __x; } |
337 | |
338 | /// Based on operator< |
339 | template<typename _Tp, typename _Seq> |
340 | inline bool |
341 | operator<=(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) |
342 | { return !(__y < __x); } |
343 | |
344 | /// Based on operator< |
345 | template<typename _Tp, typename _Seq> |
346 | inline bool |
347 | operator>=(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) |
348 | { return !(__x < __y); } |
349 | |
350 | #if __cplusplus201703L >= 201103L |
351 | template<typename _Tp, typename _Seq> |
352 | inline |
353 | #if __cplusplus201703L > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 |
354 | // Constrained free swap overload, see p0185r1 |
355 | typename enable_if<__is_swappable<_Seq>::value>::type |
356 | #else |
357 | void |
358 | #endif |
359 | swap(stack<_Tp, _Seq>& __x, stack<_Tp, _Seq>& __y) |
360 | noexcept(noexcept(__x.swap(__y))) |
361 | { __x.swap(__y); } |
362 | |
363 | template<typename _Tp, typename _Seq, typename _Alloc> |
364 | struct uses_allocator<stack<_Tp, _Seq>, _Alloc> |
365 | : public uses_allocator<_Seq, _Alloc>::type { }; |
366 | #endif // __cplusplus >= 201103L |
367 | |
368 | _GLIBCXX_END_NAMESPACE_VERSION |
369 | } // namespace |
370 | |
371 | #endif /* _STL_STACK_H */ |