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