Bug Summary

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')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name cares_wrap.cc -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/maurizio/node-v18.6.0/out -resource-dir /usr/local/lib/clang/16.0.0 -D V8_DEPRECATION_WARNINGS -D V8_IMMINENT_DEPRECATION_WARNINGS -D _GLIBCXX_USE_CXX11_ABI=1 -D NODE_OPENSSL_CONF_NAME=nodejs_conf -D NODE_OPENSSL_HAS_QUIC -D __STDC_FORMAT_MACROS -D OPENSSL_NO_PINSHARED -D OPENSSL_THREADS -D NODE_ARCH="x64" -D NODE_PLATFORM="linux" -D NODE_WANT_INTERNALS=1 -D V8_DEPRECATION_WARNINGS=1 -D NODE_OPENSSL_SYSTEM_CERT_PATH="" -D NODE_USE_NODE_CODE_CACHE=1 -D HAVE_INSPECTOR=1 -D NODE_ENABLE_LARGE_CODE_PAGES=1 -D __POSIX__ -D NODE_USE_V8_PLATFORM=1 -D NODE_HAVE_I18N_SUPPORT=1 -D HAVE_OPENSSL=1 -D OPENSSL_API_COMPAT=0x10100000L -D UCONFIG_NO_SERVICE=1 -D U_ENABLE_DYLOAD=0 -D U_STATIC_IMPLEMENTATION=1 -D U_HAVE_STD_STRING=1 -D UCONFIG_NO_BREAK_ITERATION=0 -D _LARGEFILE_SOURCE -D _FILE_OFFSET_BITS=64 -D _POSIX_C_SOURCE=200112 -D NGHTTP2_STATICLIB -D NDEBUG -D OPENSSL_USE_NODELETE -D L_ENDIAN -D OPENSSL_BUILDING_OPENSSL -D AES_ASM -D BSAES_ASM -D CMLL_ASM -D ECP_NISTZ256_ASM -D GHASH_ASM -D KECCAK1600_ASM -D MD5_ASM -D OPENSSL_BN_ASM_GF2m -D OPENSSL_BN_ASM_MONT -D OPENSSL_BN_ASM_MONT5 -D OPENSSL_CPUID_OBJ -D OPENSSL_IA32_SSE2 -D PADLOCK_ASM -D POLY1305_ASM -D SHA1_ASM -D SHA256_ASM -D SHA512_ASM -D VPAES_ASM -D WHIRLPOOL_ASM -D X25519_ASM -D OPENSSL_PIC -D NGTCP2_STATICLIB -D NGHTTP3_STATICLIB -I ../src -I /home/maurizio/node-v18.6.0/out/Release/obj/gen -I /home/maurizio/node-v18.6.0/out/Release/obj/gen/include -I /home/maurizio/node-v18.6.0/out/Release/obj/gen/src -I ../deps/googletest/include -I ../deps/histogram/src -I ../deps/uvwasi/include -I ../deps/v8/include -I ../deps/icu-small/source/i18n -I ../deps/icu-small/source/common -I ../deps/zlib -I ../deps/llhttp/include -I ../deps/cares/include -I ../deps/uv/include -I ../deps/nghttp2/lib/includes -I ../deps/brotli/c/include -I ../deps/openssl/openssl/include -I ../deps/openssl/openssl/crypto/include -I ../deps/openssl/config/archs/linux-x86_64/asm/include -I ../deps/openssl/config/archs/linux-x86_64/asm -I ../deps/ngtcp2 -I ../deps/ngtcp2/ngtcp2/lib/includes -I ../deps/ngtcp2/ngtcp2/crypto/includes -I ../deps/ngtcp2/nghttp3/lib/includes -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8 -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/x86_64-redhat-linux -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/backward -internal-isystem /usr/local/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -Wno-unused-parameter -std=gnu++17 -fdeprecated-macro -fdebug-compilation-dir=/home/maurizio/node-v18.6.0/out -ferror-limit 19 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-08-22-142216-507842-1 -x c++ ../src/cares_wrap.cc

../src/cares_wrap.cc

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
54namespace node {
55namespace cares_wrap {
56
57using v8::Array;
58using v8::Context;
59using v8::EscapableHandleScope;
60using v8::FunctionCallbackInfo;
61using v8::FunctionTemplate;
62using v8::HandleScope;
63using v8::Int32;
64using v8::Integer;
65using v8::Isolate;
66using v8::Just;
67using v8::Local;
68using v8::Maybe;
69using v8::Nothing;
70using v8::Null;
71using v8::Object;
72using v8::String;
73using v8::Value;
74
75namespace {
76
77Mutex ares_library_mutex;
78
79inline 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
83void 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
104void 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 */
111void 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
159Local<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
172Local<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
187template <typename T>
188Local<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
199int 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
283int 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
318int 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
354int 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
418int 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
460int 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
513int 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
637ChannelWrap::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
650void 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
656void 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
667GetAddrInfoReqWrap::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
674GetNameInfoReqWrap::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. */
681void 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
689void NodeAresTask::MemoryInfo(MemoryTracker* tracker) const {
690 tracker->TrackField("channel", channel);
1
Calling 'MemoryTracker::TrackField'
691}
692
693/* Allocates and returns a new NodeAresTask */
694NodeAresTask* 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
710void 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
744void 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
758void 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
766ChannelWrap::~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
779void 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 */
792void 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
830int AnyTraits::Send(QueryWrap<AnyTraits>* wrap, const char* name) {
831 wrap->AresQuery(name, ns_c_in, ns_t_any);
832 return 0;
833}
834
835int ATraits::Send(QueryWrap<ATraits>* wrap, const char* name) {
836 wrap->AresQuery(name, ns_c_in, ns_t_a);
837 return 0;
838}
839
840int AaaaTraits::Send(QueryWrap<AaaaTraits>* wrap, const char* name) {
841 wrap->AresQuery(name, ns_c_in, ns_t_aaaa);
842 return 0;
843}
844
845int CaaTraits::Send(QueryWrap<CaaTraits>* wrap, const char* name) {
846 wrap->AresQuery(name, ns_c_in, T_CAA257);
847 return 0;
848}
849
850int CnameTraits::Send(QueryWrap<CnameTraits>* wrap, const char* name) {
851 wrap->AresQuery(name, ns_c_in, ns_t_cname);
852 return 0;
853}
854
855int MxTraits::Send(QueryWrap<MxTraits>* wrap, const char* name) {
856 wrap->AresQuery(name, ns_c_in, ns_t_mx);
857 return 0;
858}
859
860int NsTraits::Send(QueryWrap<NsTraits>* wrap, const char* name) {
861 wrap->AresQuery(name, ns_c_in, ns_t_ns);
862 return 0;
863}
864
865int TxtTraits::Send(QueryWrap<TxtTraits>* wrap, const char* name) {
866 wrap->AresQuery(name, ns_c_in, ns_t_txt);
867 return 0;
868}
869
870int SrvTraits::Send(QueryWrap<SrvTraits>* wrap, const char* name) {
871 wrap->AresQuery(name, ns_c_in, ns_t_srv);
872 return 0;
873}
874
875int PtrTraits::Send(QueryWrap<PtrTraits>* wrap, const char* name) {
876 wrap->AresQuery(name, ns_c_in, ns_t_ptr);
877 return 0;
878}
879
880int NaptrTraits::Send(QueryWrap<NaptrTraits>* wrap, const char* name) {
881 wrap->AresQuery(name, ns_c_in, ns_t_naptr);
882 return 0;
883}
884
885int SoaTraits::Send(QueryWrap<SoaTraits>* wrap, const char* name) {
886 wrap->AresQuery(name, ns_c_in, ns_t_soa);
887 return 0;
888}
889
890int 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
1057int 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
1091int 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
1125int 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
1147int 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
1170int 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
1193int 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
1216int 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
1238int 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
1260int 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
1284int 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
1306int 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
1357int 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
1386int 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
1401namespace {
1402template <class Wrap>
1403static 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
1430void 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
1502void 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
1536using ParseIPResult =
1537 decltype(static_cast<ares_addr_port_node*>(nullptr)->addr);
1538
1539int 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
1547void 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
1563void 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
1623void 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
1655void 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
1693void 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
1774void 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
1838void 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
1848const char EMSG_ESETSRVPENDING[] = "There are pending queries.";
1849void 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
1860inline 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
1885void 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
1960NODE_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
); }

../src/memory_tracker-inl.h

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
8namespace node {
9
10// Fallback edge_name if node_name is not available, or "" if edge_name
11// is not available either.
12inline 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
22class 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
78void 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
84void 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
92void MemoryTracker::TrackField(const char* edge_name,
93 const MemoryRetainer& value,
94 const char* node_name) {
95 TrackField(edge_name, &value);
96}
97
98void MemoryTracker::TrackField(const char* edge_name,
99 const MemoryRetainer* value,
100 const char* node_name) {
101 if (value == nullptr) return;
2
Assuming the condition is false
3
Taking false branch
102 auto it = seen_.find(value);
103 if (it != seen_.end()) {
4
Taking false branch
104 graph_->AddEdge(CurrentNode(), it->second, edge_name);
105 } else {
106 Track(value, edge_name);
5
Calling 'MemoryTracker::Track'
107 }
108}
109
110template <typename T, typename D>
111void 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
120template <typename T>
121void 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
130template <typename T, bool kIsWeak>
131void 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
138template <typename T, typename Iterator>
139void 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
160template <typename T>
161void 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
176template <typename T, typename test_for_number, typename dummy>
177void 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
184template <typename T, typename U>
185void 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
199template <typename T>
200void 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
206template <typename T>
207void 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
213template <typename T>
214void 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
221template <typename T>
222void 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
229template <typename T>
230void 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
236void 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
242void 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
248void 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
254void 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
260void 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
266template <class NativeT, class V8T>
267void MemoryTracker::TrackField(const char* name,
268 const AliasedBufferBase<NativeT, V8T>& value,
269 const char* node_name) {
270 TrackField(name, value.GetJSArray(), "AliasedBuffer");
271}
272
273void 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()) {
6
Taking false branch
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);
7
Calling 'MemoryTracker::PushNode'
12
Returning from 'MemoryTracker::PushNode'
13
'n' initialized here
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)
;
14
Assuming the condition is true
15
Assuming pointer value is null
16
Taking false branch
17
Loop condition is false. Exiting loop
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)
;
18
Access to field 'size_' results in a dereference of a null pointer (loaded from variable 'n')
287 PopNode();
288}
289
290void 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
297MemoryRetainerNode* MemoryTracker::CurrentNode() const {
298 if (node_stack_.empty()) return nullptr;
299 return node_stack_.top();
300}
301
302MemoryRetainerNode* 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
322MemoryRetainerNode* 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
333MemoryRetainerNode* MemoryTracker::PushNode(const MemoryRetainer* retainer,
334 const char* edge_name) {
335 MemoryRetainerNode* n = AddNode(retainer, edge_name);
336 node_stack_.push(n);
8
Calling 'stack::push'
10
Returning from 'stack::push'
337 return n;
11
Returning pointer (loaded from 'n')
338}
339
340MemoryRetainerNode* 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
348void 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_

/usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/bits/stl_stack.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
65namespace 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); }
9
Value assigned to 'n'
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 */