diff --git a/src/README.md b/src/README.md index 4471dd7721ad8c..a97e1b9ba52e8f 100644 --- a/src/README.md +++ b/src/README.md @@ -474,7 +474,7 @@ void Initialize(Local target, SetProtoMethod(isolate, channel_wrap, "queryA", Query); // ... SetProtoMethod(isolate, channel_wrap, "querySoa", Query); - SetProtoMethod(isolate, channel_wrap, "getHostByAddr", Query); + SetProtoMethod(isolate, channel_wrap, "getHostByAddr", Query); SetProtoMethodNoSideEffect(isolate, channel_wrap, "getServers", GetServers); diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index fc8f361614ba5f..6290bcd37f3411 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -76,6 +76,7 @@ using v8::JustVoid; using v8::Local; using v8::LocalVector; using v8::Maybe; +using v8::MaybeLocal; using v8::Nothing; using v8::Null; using v8::Object; @@ -163,29 +164,31 @@ void ares_sockstate_cb(void* data, ares_socket_t sock, int read, int write) { } } -Local HostentToNames(Environment* env, struct hostent* host) { +MaybeLocal HostentToNames(Environment* env, struct hostent* host) { EscapableHandleScope scope(env->isolate()); LocalVector names(env->isolate()); - for (uint32_t i = 0; host->h_aliases[i] != nullptr; ++i) + for (uint32_t i = 0; host->h_aliases[i] != nullptr; ++i) { names.emplace_back(OneByteString(env->isolate(), host->h_aliases[i])); + } - Local ret = Array::New(env->isolate(), names.data(), names.size()); - - return scope.Escape(ret); + return scope.Escape(Array::New(env->isolate(), names.data(), names.size())); } -Local HostentToNames(Environment* env, - struct hostent* host, - Local names) { +MaybeLocal HostentToNames(Environment* env, + struct hostent* host, + Local names) { size_t offset = names->Length(); for (uint32_t i = 0; host->h_aliases[i] != nullptr; ++i) { - names->Set( - env->context(), - i + offset, - OneByteString(env->isolate(), host->h_aliases[i])).Check(); + if (names + ->Set(env->context(), + i + offset, + OneByteString(env->isolate(), host->h_aliases[i])) + .IsNothing()) { + return {}; + } } return names; @@ -197,20 +200,20 @@ Local AddrTTLToArray( const T* addrttls, size_t naddrttls) { MaybeStackBuffer, 8> ttls(naddrttls); - for (size_t i = 0; i < naddrttls; i++) + for (size_t i = 0; i < naddrttls; i++) { ttls[i] = Integer::NewFromUnsigned(env->isolate(), addrttls[i].ttl); + } return Array::New(env->isolate(), ttls.out(), naddrttls); } -int ParseGeneralReply( - Environment* env, - const unsigned char* buf, - int len, - int* type, - Local ret, - void* addrttls = nullptr, - int* naddrttls = nullptr) { +Maybe ParseGeneralReply(Environment* env, + const unsigned char* buf, + int len, + int* type, + Local ret, + void* addrttls = nullptr, + int* naddrttls = nullptr) { HandleScope handle_scope(env->isolate()); hostent* host; @@ -242,8 +245,7 @@ int ParseGeneralReply( UNREACHABLE("Bad NS type"); } - if (status != ARES_SUCCESS) - return status; + if (status != ARES_SUCCESS) return Just(status); CHECK_NOT_NULL(host); HostEntPointer ptr(host); @@ -256,22 +258,29 @@ int ParseGeneralReply( // A cname lookup always returns a single record but we follow the // common API here. *type = ns_t_cname; - ret->Set(env->context(), - ret->Length(), - OneByteString(env->isolate(), ptr->h_name)).Check(); - return ARES_SUCCESS; + if (ret->Set(env->context(), + ret->Length(), + OneByteString(env->isolate(), ptr->h_name)) + .IsNothing()) { + return Nothing(); + } + return Just(ARES_SUCCESS); } if (*type == ns_t_cname_or_a) *type = ns_t_a; if (*type == ns_t_ns) { - HostentToNames(env, ptr.get(), ret); + if (HostentToNames(env, ptr.get(), ret).IsEmpty()) { + return Nothing(); + } } else if (*type == ns_t_ptr) { uint32_t offset = ret->Length(); for (uint32_t i = 0; ptr->h_aliases[i] != nullptr; i++) { auto alias = OneByteString(env->isolate(), ptr->h_aliases[i]); - ret->Set(env->context(), i + offset, alias).Check(); + if (ret->Set(env->context(), i + offset, alias).IsNothing()) { + return Nothing(); + } } } else { uint32_t offset = ret->Length(); @@ -279,88 +288,110 @@ int ParseGeneralReply( for (uint32_t i = 0; ptr->h_addr_list[i] != nullptr; ++i) { uv_inet_ntop(ptr->h_addrtype, ptr->h_addr_list[i], ip, sizeof(ip)); auto address = OneByteString(env->isolate(), ip); - ret->Set(env->context(), i + offset, address).Check(); + if (ret->Set(env->context(), i + offset, address).IsNothing()) { + return Nothing(); + } } } - return ARES_SUCCESS; + return Just(ARES_SUCCESS); } - -int ParseMxReply( - Environment* env, - const unsigned char* buf, - int len, - Local ret, - bool need_type = false) { +Maybe ParseMxReply(Environment* env, + const unsigned char* buf, + int len, + Local ret, + bool need_type = false) { HandleScope handle_scope(env->isolate()); struct ares_mx_reply* mx_start; int status = ares_parse_mx_reply(buf, len, &mx_start); - if (status != ARES_SUCCESS) - return status; + if (status != ARES_SUCCESS) return Just(status); uint32_t offset = ret->Length(); ares_mx_reply* current = mx_start; for (uint32_t i = 0; current != nullptr; ++i, current = current->next) { Local mx_record = Object::New(env->isolate()); - mx_record->Set(env->context(), - env->exchange_string(), - OneByteString(env->isolate(), current->host)).Check(); - mx_record->Set(env->context(), - env->priority_string(), - Integer::New(env->isolate(), current->priority)).Check(); - if (need_type) - mx_record->Set(env->context(), - env->type_string(), - env->dns_mx_string()).Check(); + if (mx_record + ->Set(env->context(), + env->exchange_string(), + OneByteString(env->isolate(), current->host)) + .IsNothing() || + mx_record + ->Set(env->context(), + env->priority_string(), + Integer::New(env->isolate(), current->priority)) + .IsNothing()) { + ares_free_data(mx_start); + return Nothing(); + } + if (need_type && + mx_record->Set(env->context(), env->type_string(), env->dns_mx_string()) + .IsNothing()) { + ares_free_data(mx_start); + return Nothing(); + } - ret->Set(env->context(), i + offset, mx_record).Check(); + if (ret->Set(env->context(), i + offset, mx_record).IsNothing()) { + ares_free_data(mx_start); + return Nothing(); + } } ares_free_data(mx_start); - return ARES_SUCCESS; + return Just(ARES_SUCCESS); } -int ParseCaaReply( - Environment* env, - const unsigned char* buf, - int len, - Local ret, - bool need_type = false) { +Maybe ParseCaaReply(Environment* env, + const unsigned char* buf, + int len, + Local ret, + bool need_type = false) { HandleScope handle_scope(env->isolate()); struct ares_caa_reply* caa_start; int status = ares_parse_caa_reply(buf, len, &caa_start); - if (status != ARES_SUCCESS) - return status; + if (status != ARES_SUCCESS) return Just(status); uint32_t offset = ret->Length(); ares_caa_reply* current = caa_start; for (uint32_t i = 0; current != nullptr; ++i, current = current->next) { Local caa_record = Object::New(env->isolate()); - caa_record->Set(env->context(), - env->dns_critical_string(), - Integer::New(env->isolate(), current->critical)).Check(); - caa_record->Set(env->context(), - OneByteString(env->isolate(), current->property), - OneByteString(env->isolate(), current->value)).Check(); - if (need_type) - caa_record->Set(env->context(), - env->type_string(), - env->dns_caa_string()).Check(); + if (caa_record + ->Set(env->context(), + env->dns_critical_string(), + Integer::New(env->isolate(), current->critical)) + .IsNothing() || + caa_record + ->Set(env->context(), + OneByteString(env->isolate(), current->property), + OneByteString(env->isolate(), current->value)) + .IsNothing()) { + ares_free_data(caa_start); + return Nothing(); + } + if (need_type && + caa_record + ->Set(env->context(), env->type_string(), env->dns_caa_string()) + .IsNothing()) { + ares_free_data(caa_start); + return Nothing(); + } - ret->Set(env->context(), i + offset, caa_record).Check(); + if (ret->Set(env->context(), i + offset, caa_record).IsNothing()) { + ares_free_data(caa_start); + return Nothing(); + } } ares_free_data(caa_start); - return ARES_SUCCESS; + return Just(ARES_SUCCESS); } -int ParseTlsaReply(Environment* env, - unsigned char* buf, - int len, - Local ret) { +Maybe ParseTlsaReply(Environment* env, + unsigned char* buf, + int len, + Local ret) { EscapableHandleScope handle_scope(env->isolate()); ares_dns_record_t* dnsrec = nullptr; @@ -368,7 +399,7 @@ int ParseTlsaReply(Environment* env, int status = ares_dns_parse(buf, len, 0, &dnsrec); if (status != ARES_SUCCESS) { ares_dns_record_destroy(dnsrec); - return status; + return Just(status); } uint32_t offset = ret->Length(); @@ -392,43 +423,45 @@ int ParseTlsaReply(Environment* env, memcpy(data_ab->Data(), data, data_len); Local tlsa_rec = Object::New(env->isolate()); - tlsa_rec - ->Set(env->context(), - env->cert_usage_string(), - Integer::NewFromUnsigned(env->isolate(), certusage)) - .Check(); - tlsa_rec - ->Set(env->context(), - env->selector_string(), - Integer::NewFromUnsigned(env->isolate(), selector)) - .Check(); - tlsa_rec - ->Set(env->context(), - env->match_string(), - Integer::NewFromUnsigned(env->isolate(), match)) - .Check(); - tlsa_rec->Set(env->context(), env->data_string(), data_ab).Check(); - - ret->Set(env->context(), offset + i, tlsa_rec).Check(); + + if (tlsa_rec + ->Set(env->context(), + env->cert_usage_string(), + Integer::NewFromUnsigned(env->isolate(), certusage)) + .IsNothing() || + tlsa_rec + ->Set(env->context(), + env->selector_string(), + Integer::NewFromUnsigned(env->isolate(), selector)) + .IsNothing() || + tlsa_rec + ->Set(env->context(), + env->match_string(), + Integer::NewFromUnsigned(env->isolate(), match)) + .IsNothing() || + tlsa_rec->Set(env->context(), env->data_string(), data_ab) + .IsNothing() || + ret->Set(env->context(), offset + i, tlsa_rec).IsNothing()) { + ares_dns_record_destroy(dnsrec); + return Nothing(); + } } ares_dns_record_destroy(dnsrec); - return ARES_SUCCESS; + return Just(ARES_SUCCESS); } -int ParseTxtReply( - Environment* env, - const unsigned char* buf, - int len, - Local ret, - bool need_type = false) { +Maybe ParseTxtReply(Environment* env, + const unsigned char* buf, + int len, + Local ret, + bool need_type = false) { HandleScope handle_scope(env->isolate()); struct ares_txt_ext* txt_out; int status = ares_parse_txt_reply_ext(buf, len, &txt_out); - if (status != ARES_SUCCESS) - return status; + if (status != ARES_SUCCESS) return Just(status); Local txt_chunk; @@ -444,13 +477,19 @@ int ParseTxtReply( if (!txt_chunk.IsEmpty()) { if (need_type) { Local elem = Object::New(env->isolate()); - elem->Set(env->context(), env->entries_string(), txt_chunk).Check(); - elem->Set(env->context(), - env->type_string(), - env->dns_txt_string()).Check(); - ret->Set(env->context(), offset + i++, elem).Check(); - } else { - ret->Set(env->context(), offset + i++, txt_chunk).Check(); + if (elem->Set(env->context(), env->entries_string(), txt_chunk) + .IsNothing() || + elem->Set( + env->context(), env->type_string(), env->dns_txt_string()) + .IsNothing() || + ret->Set(env->context(), offset + i++, elem).IsNothing()) { + ares_free_data(txt_out); + return Nothing(); + } + } else if (ret->Set(env->context(), offset + i++, txt_chunk) + .IsNothing()) { + ares_free_data(txt_out); + return Nothing(); } } @@ -458,128 +497,163 @@ int ParseTxtReply( j = 0; } - txt_chunk->Set(env->context(), j++, txt).Check(); + if (txt_chunk->Set(env->context(), j++, txt).IsNothing()) { + ares_free_data(txt_out); + return Nothing(); + } } // Push last chunk if it isn't empty if (!txt_chunk.IsEmpty()) { if (need_type) { Local elem = Object::New(env->isolate()); - elem->Set(env->context(), env->entries_string(), txt_chunk).Check(); - elem->Set(env->context(), - env->type_string(), - env->dns_txt_string()).Check(); - ret->Set(env->context(), offset + i, elem).Check(); - } else { - ret->Set(env->context(), offset + i, txt_chunk).Check(); + if (elem->Set(env->context(), env->entries_string(), txt_chunk) + .IsNothing() || + elem->Set(env->context(), env->type_string(), env->dns_txt_string()) + .IsNothing() || + ret->Set(env->context(), offset + i, elem).IsNothing()) { + ares_free_data(txt_out); + return Nothing(); + } + } else if (ret->Set(env->context(), offset + i, txt_chunk).IsNothing()) { + ares_free_data(txt_out); + return Nothing(); } } ares_free_data(txt_out); - return ARES_SUCCESS; + return Just(ARES_SUCCESS); } - -int ParseSrvReply( - Environment* env, - const unsigned char* buf, - int len, - Local ret, - bool need_type = false) { +Maybe ParseSrvReply(Environment* env, + const unsigned char* buf, + int len, + Local ret, + bool need_type = false) { HandleScope handle_scope(env->isolate()); struct ares_srv_reply* srv_start; int status = ares_parse_srv_reply(buf, len, &srv_start); - if (status != ARES_SUCCESS) - return status; + if (status != ARES_SUCCESS) return Just(status); ares_srv_reply* current = srv_start; int offset = ret->Length(); for (uint32_t i = 0; current != nullptr; ++i, current = current->next) { Local srv_record = Object::New(env->isolate()); - srv_record->Set(env->context(), - env->name_string(), - OneByteString(env->isolate(), current->host)).Check(); - srv_record->Set(env->context(), - env->port_string(), - Integer::New(env->isolate(), current->port)).Check(); - srv_record->Set(env->context(), - env->priority_string(), - Integer::New(env->isolate(), current->priority)).Check(); - srv_record->Set(env->context(), - env->weight_string(), - Integer::New(env->isolate(), current->weight)).Check(); - if (need_type) - srv_record->Set(env->context(), - env->type_string(), - env->dns_srv_string()).Check(); - - ret->Set(env->context(), i + offset, srv_record).Check(); + + if (srv_record + ->Set(env->context(), + env->name_string(), + OneByteString(env->isolate(), current->host)) + .IsNothing() || + srv_record + ->Set(env->context(), + env->port_string(), + Integer::New(env->isolate(), current->port)) + .IsNothing() || + srv_record + ->Set(env->context(), + env->priority_string(), + Integer::New(env->isolate(), current->priority)) + .IsNothing() || + srv_record + ->Set(env->context(), + env->weight_string(), + Integer::New(env->isolate(), current->weight)) + .IsNothing()) { + ares_free_data(srv_start); + return Nothing(); + } + if (need_type && + srv_record + ->Set(env->context(), env->type_string(), env->dns_srv_string()) + .IsNothing()) { + ares_free_data(srv_start); + return Nothing(); + } + + if (ret->Set(env->context(), i + offset, srv_record).IsNothing()) { + ares_free_data(srv_start); + return Nothing(); + } } ares_free_data(srv_start); - return ARES_SUCCESS; + return Just(ARES_SUCCESS); } - -int ParseNaptrReply( - Environment* env, - const unsigned char* buf, - int len, - Local ret, - bool need_type = false) { +Maybe ParseNaptrReply(Environment* env, + const unsigned char* buf, + int len, + Local ret, + bool need_type = false) { HandleScope handle_scope(env->isolate()); ares_naptr_reply* naptr_start; int status = ares_parse_naptr_reply(buf, len, &naptr_start); - if (status != ARES_SUCCESS) - return status; + if (status != ARES_SUCCESS) return Just(status); ares_naptr_reply* current = naptr_start; int offset = ret->Length(); for (uint32_t i = 0; current != nullptr; ++i, current = current->next) { Local naptr_record = Object::New(env->isolate()); - naptr_record->Set(env->context(), - env->flags_string(), - OneByteString(env->isolate(), current->flags)).Check(); - naptr_record->Set(env->context(), - env->service_string(), - OneByteString(env->isolate(), - current->service)).Check(); - naptr_record->Set(env->context(), - env->regexp_string(), - OneByteString(env->isolate(), - current->regexp)).Check(); - naptr_record->Set(env->context(), - env->replacement_string(), - OneByteString(env->isolate(), - current->replacement)).Check(); - naptr_record->Set(env->context(), - env->order_string(), - Integer::New(env->isolate(), current->order)).Check(); - naptr_record->Set(env->context(), - env->preference_string(), - Integer::New(env->isolate(), - current->preference)).Check(); - if (need_type) - naptr_record->Set(env->context(), - env->type_string(), - env->dns_naptr_string()).Check(); - - ret->Set(env->context(), i + offset, naptr_record).Check(); + + if (naptr_record + ->Set(env->context(), + env->flags_string(), + OneByteString(env->isolate(), current->flags)) + .IsNothing() || + naptr_record + ->Set(env->context(), + env->service_string(), + OneByteString(env->isolate(), current->service)) + .IsNothing() || + naptr_record + ->Set(env->context(), + env->regexp_string(), + OneByteString(env->isolate(), current->regexp)) + .IsNothing() || + naptr_record + ->Set(env->context(), + env->replacement_string(), + OneByteString(env->isolate(), current->replacement)) + .IsNothing() || + naptr_record + ->Set(env->context(), + env->order_string(), + Integer::New(env->isolate(), current->order)) + .IsNothing() || + naptr_record + ->Set(env->context(), + env->preference_string(), + Integer::New(env->isolate(), current->preference)) + .IsNothing()) { + ares_free_data(naptr_start); + return Nothing(); + } + if (need_type && + naptr_record + ->Set(env->context(), env->type_string(), env->dns_naptr_string()) + .IsNothing()) { + ares_free_data(naptr_start); + return Nothing(); + } + + if (ret->Set(env->context(), i + offset, naptr_record).IsNothing()) { + ares_free_data(naptr_start); + return Nothing(); + } } ares_free_data(naptr_start); - return ARES_SUCCESS; + return Just(ARES_SUCCESS); } - -int ParseSoaReply( - Environment* env, - unsigned char* buf, - int len, - Local* ret) { +Maybe ParseSoaReply(Environment* env, + unsigned char* buf, + int len, + Local* ret) { EscapableHandleScope handle_scope(env->isolate()); // Manage memory using standardard smart pointer std::unique_tr @@ -596,13 +670,13 @@ int ParseSoaReply( int status = ares_expand_name(ptr, buf, len, &name_temp, &temp_len); if (status != ARES_SUCCESS) { // returns EBADRESP in case of invalid input - return status == ARES_EBADNAME ? ARES_EBADRESP : status; + return Just(status == ARES_EBADNAME ? ARES_EBADRESP : status); } const ares_unique_ptr name(name_temp); if (ptr + temp_len + NS_QFIXEDSZ > buf + len) { - return ARES_EBADRESP; + return Just(ARES_EBADRESP); } ptr += temp_len + NS_QFIXEDSZ; @@ -612,13 +686,13 @@ int ParseSoaReply( int status2 = ares_expand_name(ptr, buf, len, &rr_name_temp, &rr_temp_len); if (status2 != ARES_SUCCESS) - return status2 == ARES_EBADNAME ? ARES_EBADRESP : status2; + return Just(status2 == ARES_EBADNAME ? ARES_EBADRESP : status2); const ares_unique_ptr rr_name(rr_name_temp); ptr += rr_temp_len; if (ptr + NS_RRFIXEDSZ > buf + len) { - return ARES_EBADRESP; + return Just(ARES_EBADRESP); } const int rr_type = cares_get_16bit(ptr); @@ -634,7 +708,7 @@ int ParseSoaReply( &nsname_temp, &nsname_temp_len); if (status3 != ARES_SUCCESS) { - return status3 == ARES_EBADNAME ? ARES_EBADRESP : status3; + return Just(status3 == ARES_EBADNAME ? ARES_EBADRESP : status3); } const ares_unique_ptr nsname(nsname_temp); ptr += nsname_temp_len; @@ -645,13 +719,13 @@ int ParseSoaReply( &hostmaster_temp, &hostmaster_temp_len); if (status4 != ARES_SUCCESS) { - return status4 == ARES_EBADNAME ? ARES_EBADRESP : status4; + return Just(status4 == ARES_EBADNAME ? ARES_EBADRESP : status4); } const ares_unique_ptr hostmaster(hostmaster_temp); ptr += hostmaster_temp_len; if (ptr + 5 * 4 > buf + len) { - return ARES_EBADRESP; + return Just(ARES_EBADRESP); } const unsigned int serial = nbytes::ReadUint32BE(ptr + 0 * 4); @@ -661,32 +735,46 @@ int ParseSoaReply( const unsigned int minttl = nbytes::ReadUint32BE(ptr + 4 * 4); Local soa_record = Object::New(env->isolate()); - soa_record->Set(env->context(), - env->nsname_string(), - OneByteString(env->isolate(), nsname.get())).Check(); - soa_record->Set(env->context(), - env->hostmaster_string(), - OneByteString(env->isolate(), - hostmaster.get())).Check(); - soa_record->Set(env->context(), - env->serial_string(), - Integer::NewFromUnsigned(env->isolate(), serial)).Check(); - soa_record->Set(env->context(), - env->refresh_string(), - Integer::New(env->isolate(), refresh)).Check(); - soa_record->Set(env->context(), - env->retry_string(), - Integer::New(env->isolate(), retry)).Check(); - soa_record->Set(env->context(), - env->expire_string(), - Integer::New(env->isolate(), expire)).Check(); - soa_record->Set(env->context(), - env->minttl_string(), - Integer::NewFromUnsigned(env->isolate(), minttl)).Check(); - soa_record->Set(env->context(), - env->type_string(), - env->dns_soa_string()).Check(); - + if (soa_record + ->Set(env->context(), + env->nsname_string(), + OneByteString(env->isolate(), nsname.get())) + .IsNothing() || + soa_record + ->Set(env->context(), + env->hostmaster_string(), + OneByteString(env->isolate(), hostmaster.get())) + .IsNothing() || + soa_record + ->Set(env->context(), + env->serial_string(), + Integer::NewFromUnsigned(env->isolate(), serial)) + .IsNothing() || + soa_record + ->Set(env->context(), + env->refresh_string(), + Integer::New(env->isolate(), refresh)) + .IsNothing() || + soa_record + ->Set(env->context(), + env->retry_string(), + Integer::New(env->isolate(), retry)) + .IsNothing() || + soa_record + ->Set(env->context(), + env->expire_string(), + Integer::New(env->isolate(), expire)) + .IsNothing() || + soa_record + ->Set(env->context(), + env->minttl_string(), + Integer::NewFromUnsigned(env->isolate(), minttl)) + .IsNothing() || + soa_record + ->Set(env->context(), env->type_string(), env->dns_soa_string()) + .IsNothing()) { + return Nothing(); + } *ret = handle_scope.Escape(soa_record); break; @@ -695,7 +783,7 @@ int ParseSoaReply( ptr += rr_len; } - return ARES_SUCCESS; + return Just(ARES_SUCCESS); } } // anonymous namespace @@ -956,11 +1044,10 @@ int SoaTraits::Send(QueryWrap* wrap, const char* name) { return ARES_SUCCESS; } -int AnyTraits::Parse( - QueryAnyWrap* wrap, - const std::unique_ptr& response) { +Maybe AnyTraits::Parse(QueryAnyWrap* wrap, + const std::unique_ptr& response) { if (response->is_host) [[unlikely]] { - return ARES_EBADRESP; + return Just(ARES_EBADRESP); } unsigned char* buf = response->buf.data; @@ -978,43 +1065,44 @@ int AnyTraits::Parse( int naddrttls = arraysize(addrttls); type = ns_t_cname_or_a; - status = ParseGeneralReply(env, - buf, - len, - &type, - ret, - addrttls, - &naddrttls); + if (!ParseGeneralReply(env, buf, len, &type, ret, addrttls, &naddrttls) + .To(&status)) { + return Nothing(); + } uint32_t a_count = ret->Length(); - if (status != ARES_SUCCESS && status != ARES_ENODATA) - return status; + if (status != ARES_SUCCESS && status != ARES_ENODATA) { + return Just(status); + } if (type == ns_t_a) { CHECK_EQ(static_cast(naddrttls), a_count); for (uint32_t i = 0; i < a_count; i++) { Local obj = Object::New(env->isolate()); - obj->Set(env->context(), - env->address_string(), - ret->Get(env->context(), i).ToLocalChecked()).Check(); - obj->Set(env->context(), - env->ttl_string(), - Integer::NewFromUnsigned( - env->isolate(), addrttls[i].ttl)).Check(); - obj->Set(env->context(), - env->type_string(), - env->dns_a_string()).Check(); - ret->Set(env->context(), i, obj).Check(); + Local address; + if (!ret->Get(env->context(), i).ToLocal(&address) || + obj->Set(env->context(), env->address_string(), address) + .IsNothing() || + obj->Set(env->context(), + env->ttl_string(), + Integer::NewFromUnsigned(env->isolate(), addrttls[i].ttl)) + .IsNothing() || + obj->Set(env->context(), env->type_string(), env->dns_a_string()) + .IsNothing() || + ret->Set(env->context(), i, obj).IsNothing()) { + return Nothing(); + } } } else { for (uint32_t i = 0; i < a_count; i++) { Local obj = Object::New(env->isolate()); - obj->Set(env->context(), - env->value_string(), - ret->Get(env->context(), i).ToLocalChecked()).Check(); - obj->Set(env->context(), - env->type_string(), - env->dns_cname_string()).Check(); - ret->Set(env->context(), i, obj).Check(); + Local value; + if (!ret->Get(env->context(), i).ToLocal(&value) || + obj->Set(env->context(), env->value_string(), value).IsNothing() || + obj->Set(env->context(), env->type_string(), env->dns_cname_string()) + .IsNothing() || + ret->Set(env->context(), i, obj).IsNothing()) { + return Nothing(); + } } } @@ -1023,116 +1111,149 @@ int AnyTraits::Parse( int naddr6ttls = arraysize(addr6ttls); type = ns_t_aaaa; - status = ParseGeneralReply(env, - buf, - len, - &type, - ret, - addr6ttls, - &naddr6ttls); + if (!ParseGeneralReply(env, buf, len, &type, ret, addr6ttls, &naddr6ttls) + .To(&status)) { + return Nothing(); + } uint32_t aaaa_count = ret->Length() - a_count; if (status != ARES_SUCCESS && status != ARES_ENODATA) - return status; + return Just(status); CHECK_EQ(aaaa_count, static_cast(naddr6ttls)); CHECK_EQ(ret->Length(), a_count + aaaa_count); for (uint32_t i = a_count; i < ret->Length(); i++) { Local obj = Object::New(env->isolate()); - obj->Set(env->context(), - env->address_string(), - ret->Get(env->context(), i).ToLocalChecked()).Check(); - obj->Set(env->context(), - env->ttl_string(), - Integer::NewFromUnsigned( - env->isolate(), addr6ttls[i - a_count].ttl)).Check(); - obj->Set(env->context(), - env->type_string(), - env->dns_aaaa_string()).Check(); - ret->Set(env->context(), i, obj).Check(); + Local address; + + if (!ret->Get(env->context(), i).ToLocal(&address) || + obj->Set(env->context(), env->address_string(), address).IsNothing() || + obj->Set(env->context(), + env->ttl_string(), + Integer::NewFromUnsigned(env->isolate(), + addr6ttls[i - a_count].ttl)) + .IsNothing() || + obj->Set(env->context(), env->type_string(), env->dns_aaaa_string()) + .IsNothing() || + ret->Set(env->context(), i, obj).IsNothing()) { + return Nothing(); + } } /* Parse MX records */ - status = ParseMxReply(env, buf, len, ret, true); - if (status != ARES_SUCCESS && status != ARES_ENODATA) - return status; + if (!ParseMxReply(env, buf, len, ret, true).To(&status)) { + return Nothing(); + } + if (status != ARES_SUCCESS && status != ARES_ENODATA) { + return Just(status); + } /* Parse NS records */ type = ns_t_ns; old_count = ret->Length(); - status = ParseGeneralReply(env, buf, len, &type, ret); - if (status != ARES_SUCCESS && status != ARES_ENODATA) - return status; + if (!ParseGeneralReply(env, buf, len, &type, ret).To(&status)) { + return Nothing(); + } + if (status != ARES_SUCCESS && status != ARES_ENODATA) { + return Just(status); + } for (uint32_t i = old_count; i < ret->Length(); i++) { Local obj = Object::New(env->isolate()); - obj->Set(env->context(), - env->value_string(), - ret->Get(env->context(), i).ToLocalChecked()).Check(); - obj->Set(env->context(), - env->type_string(), - env->dns_ns_string()).Check(); - ret->Set(env->context(), i, obj).Check(); + Local value; + + if (!ret->Get(env->context(), i).ToLocal(&value) || + obj->Set(env->context(), env->value_string(), value).IsNothing() || + obj->Set(env->context(), env->type_string(), env->dns_ns_string()) + .IsNothing() || + ret->Set(env->context(), i, obj).IsNothing()) { + return Nothing(); + } } /* Parse TXT records */ - status = ParseTxtReply(env, buf, len, ret, true); - if (status != ARES_SUCCESS && status != ARES_ENODATA) - return status; + if (!ParseTxtReply(env, buf, len, ret, true).To(&status)) { + return Nothing(); + } + if (status != ARES_SUCCESS && status != ARES_ENODATA) { + return Just(status); + } /* Parse SRV records */ - status = ParseSrvReply(env, buf, len, ret, true); - if (status != ARES_SUCCESS && status != ARES_ENODATA) - return status; + if (!ParseSrvReply(env, buf, len, ret, true).To(&status)) { + return Nothing(); + } + if (status != ARES_SUCCESS && status != ARES_ENODATA) { + return Just(status); + } /* Parse PTR records */ type = ns_t_ptr; old_count = ret->Length(); - status = ParseGeneralReply(env, buf, len, &type, ret); + if (!ParseGeneralReply(env, buf, len, &type, ret).To(&status)) { + return Nothing(); + } if (status != ARES_SUCCESS && status != ARES_ENODATA) - return status; + return Just(status); for (uint32_t i = old_count; i < ret->Length(); i++) { Local obj = Object::New(env->isolate()); - obj->Set(env->context(), - env->value_string(), - ret->Get(env->context(), i).ToLocalChecked()).Check(); - obj->Set(env->context(), - env->type_string(), - env->dns_ptr_string()).Check(); - ret->Set(env->context(), i, obj).Check(); + Local value; + + if (!ret->Get(env->context(), i).ToLocal(&value) || + obj->Set(env->context(), env->value_string(), value).IsNothing() || + obj->Set(env->context(), env->type_string(), env->dns_ptr_string()) + .IsNothing() || + ret->Set(env->context(), i, obj).IsNothing()) { + return Nothing(); + } } /* Parse NAPTR records */ - status = ParseNaptrReply(env, buf, len, ret, true); - if (status != ARES_SUCCESS && status != ARES_ENODATA) - return status; + if (!ParseNaptrReply(env, buf, len, ret, true).To(&status)) { + return Nothing(); + } + if (status != ARES_SUCCESS && status != ARES_ENODATA) { + return Just(status); + } /* Parse SOA records */ Local soa_record = Local(); - status = ParseSoaReply(env, buf, len, &soa_record); - if (status != ARES_SUCCESS && status != ARES_ENODATA) - return status; + if (!ParseSoaReply(env, buf, len, &soa_record).To(&status)) { + return Nothing(); + } + if (status != ARES_SUCCESS && status != ARES_ENODATA) { + return Just(status); + } - if (!soa_record.IsEmpty()) - ret->Set(env->context(), ret->Length(), soa_record).Check(); + if (!soa_record.IsEmpty()) { + if (ret->Set(env->context(), ret->Length(), soa_record).IsNothing()) { + return Just(ARES_ENOMEM); + } + } /* Parse TLSA records */ - status = ParseTlsaReply(env, buf, len, ret); - if (status != ARES_SUCCESS && status != ARES_ENODATA) return status; + if (!ParseTlsaReply(env, buf, len, ret).To(&status)) { + return Nothing(); + } + if (status != ARES_SUCCESS && status != ARES_ENODATA) { + return Just(status); + } /* Parse CAA records */ - status = ParseCaaReply(env, buf, len, ret, true); - if (status != ARES_SUCCESS && status != ARES_ENODATA) - return status; + if (!ParseCaaReply(env, buf, len, ret, true).To(&status)) { + return Nothing(); + } + if (status != ARES_SUCCESS && status != ARES_ENODATA) { + return Just(status); + } wrap->CallOnComplete(ret); - return ARES_SUCCESS; + return Just(ARES_SUCCESS); } -int ATraits::Parse( - QueryAWrap* wrap, - const std::unique_ptr& response) { +Maybe ATraits::Parse(QueryAWrap* wrap, + const std::unique_ptr& response) { if (response->is_host) [[unlikely]] { - return ARES_EBADRESP; + return Just(ARES_EBADRESP); } unsigned char* buf = response->buf.data; @@ -1147,27 +1268,24 @@ int ATraits::Parse( Local ret = Array::New(env->isolate()); int type = ns_t_a; - status = ParseGeneralReply(env, - buf, - len, - &type, - ret, - addrttls, - &naddrttls); - if (status != ARES_SUCCESS) - return status; + if (!ParseGeneralReply(env, buf, len, &type, ret, addrttls, &naddrttls) + .To(&status)) { + return Nothing(); + } + if (status != ARES_SUCCESS) { + return Just(status); + } Local ttls = AddrTTLToArray(env, addrttls, naddrttls); wrap->CallOnComplete(ret, ttls); - return ARES_SUCCESS; + return Just(ARES_SUCCESS); } -int AaaaTraits::Parse( - QueryAaaaWrap* wrap, - const std::unique_ptr& response) { +Maybe AaaaTraits::Parse(QueryAaaaWrap* wrap, + const std::unique_ptr& response) { if (response->is_host) [[unlikely]] { - return ARES_EBADRESP; + return Just(ARES_EBADRESP); } unsigned char* buf = response->buf.data; @@ -1182,27 +1300,24 @@ int AaaaTraits::Parse( Local ret = Array::New(env->isolate()); int type = ns_t_aaaa; - status = ParseGeneralReply(env, - buf, - len, - &type, - ret, - addrttls, - &naddrttls); - if (status != ARES_SUCCESS) - return status; + if (!ParseGeneralReply(env, buf, len, &type, ret, addrttls, &naddrttls) + .To(&status)) { + return Nothing(); + } + if (status != ARES_SUCCESS) { + return Just(status); + } Local ttls = AddrTTLToArray(env, addrttls, naddrttls); wrap->CallOnComplete(ret, ttls); - return ARES_SUCCESS; + return Just(ARES_SUCCESS); } -int CaaTraits::Parse( - QueryCaaWrap* wrap, - const std::unique_ptr& response) { +Maybe CaaTraits::Parse(QueryCaaWrap* wrap, + const std::unique_ptr& response) { if (response->is_host) [[unlikely]] { - return ARES_EBADRESP; + return Just(ARES_EBADRESP); } unsigned char* buf = response->buf.data; @@ -1213,19 +1328,22 @@ int CaaTraits::Parse( Context::Scope context_scope(env->context()); Local ret = Array::New(env->isolate()); - int status = ParseCaaReply(env, buf, len, ret); - if (status != ARES_SUCCESS) - return status; + int status; + if (!ParseCaaReply(env, buf, len, ret).To(&status)) { + return Nothing(); + } + if (status != ARES_SUCCESS) { + return Just(status); + } wrap->CallOnComplete(ret); - return ARES_SUCCESS; + return Just(ARES_SUCCESS); } -int CnameTraits::Parse( - QueryCnameWrap* wrap, - const std::unique_ptr& response) { +Maybe CnameTraits::Parse(QueryCnameWrap* wrap, + const std::unique_ptr& response) { if (response->is_host) [[unlikely]] { - return ARES_EBADRESP; + return Just(ARES_EBADRESP); } unsigned char* buf = response->buf.data; @@ -1237,19 +1355,22 @@ int CnameTraits::Parse( Local ret = Array::New(env->isolate()); int type = ns_t_cname; - int status = ParseGeneralReply(env, buf, len, &type, ret); - if (status != ARES_SUCCESS) - return status; + int status; + if (!ParseGeneralReply(env, buf, len, &type, ret).To(&status)) { + return Nothing(); + } + if (status != ARES_SUCCESS) { + return Just(status); + } wrap->CallOnComplete(ret); - return ARES_SUCCESS; + return Just(ARES_SUCCESS); } -int MxTraits::Parse( - QueryMxWrap* wrap, - const std::unique_ptr& response) { +Maybe MxTraits::Parse(QueryMxWrap* wrap, + const std::unique_ptr& response) { if (response->is_host) [[unlikely]] { - return ARES_EBADRESP; + return Just(ARES_EBADRESP); } unsigned char* buf = response->buf.data; @@ -1260,20 +1381,23 @@ int MxTraits::Parse( Context::Scope context_scope(env->context()); Local mx_records = Array::New(env->isolate()); - int status = ParseMxReply(env, buf, len, mx_records); + int status; + if (!ParseMxReply(env, buf, len, mx_records).To(&status)) { + return Nothing(); + } - if (status != ARES_SUCCESS) - return status; + if (status != ARES_SUCCESS) { + return Just(status); + } wrap->CallOnComplete(mx_records); - return ARES_SUCCESS; + return Just(ARES_SUCCESS); } -int NsTraits::Parse( - QueryNsWrap* wrap, - const std::unique_ptr& response) { +Maybe NsTraits::Parse(QueryNsWrap* wrap, + const std::unique_ptr& response) { if (response->is_host) [[unlikely]] { - return ARES_EBADRESP; + return Just(ARES_EBADRESP); } unsigned char* buf = response->buf.data; @@ -1285,18 +1409,22 @@ int NsTraits::Parse( int type = ns_t_ns; Local names = Array::New(env->isolate()); - int status = ParseGeneralReply(env, buf, len, &type, names); - if (status != ARES_SUCCESS) - return status; + int status; + if (!ParseGeneralReply(env, buf, len, &type, names).To(&status)) { + return Nothing(); + } + if (status != ARES_SUCCESS) { + return Just(status); + } wrap->CallOnComplete(names); - return ARES_SUCCESS; + return Just(ARES_SUCCESS); } -int TlsaTraits::Parse(QueryTlsaWrap* wrap, - const std::unique_ptr& response) { +Maybe TlsaTraits::Parse(QueryTlsaWrap* wrap, + const std::unique_ptr& response) { if (response->is_host) [[unlikely]] { - return ARES_EBADRESP; + return Just(ARES_EBADRESP); } unsigned char* buf = response->buf.data; @@ -1307,18 +1435,22 @@ int TlsaTraits::Parse(QueryTlsaWrap* wrap, Context::Scope context_scope(env->context()); Local tlsa_records = Array::New(env->isolate()); - int status = ParseTlsaReply(env, buf, len, tlsa_records); - if (status != ARES_SUCCESS) return status; + int status; + if (!ParseTlsaReply(env, buf, len, tlsa_records).To(&status)) { + return Nothing(); + } + if (status != ARES_SUCCESS) { + return Just(status); + } wrap->CallOnComplete(tlsa_records); - return ARES_SUCCESS; + return Just(ARES_SUCCESS); } -int TxtTraits::Parse( - QueryTxtWrap* wrap, - const std::unique_ptr& response) { +Maybe TxtTraits::Parse(QueryTxtWrap* wrap, + const std::unique_ptr& response) { if (response->is_host) [[unlikely]] { - return ARES_EBADRESP; + return Just(ARES_EBADRESP); } unsigned char* buf = response->buf.data; @@ -1329,19 +1461,22 @@ int TxtTraits::Parse( Context::Scope context_scope(env->context()); Local txt_records = Array::New(env->isolate()); - int status = ParseTxtReply(env, buf, len, txt_records); - if (status != ARES_SUCCESS) - return status; + int status; + if (!ParseTxtReply(env, buf, len, txt_records).To(&status)) { + return Nothing(); + } + if (status != ARES_SUCCESS) { + return Just(status); + } wrap->CallOnComplete(txt_records); - return ARES_SUCCESS; + return Just(ARES_SUCCESS); } -int SrvTraits::Parse( - QuerySrvWrap* wrap, - const std::unique_ptr& response) { +Maybe SrvTraits::Parse(QuerySrvWrap* wrap, + const std::unique_ptr& response) { if (response->is_host) [[unlikely]] { - return ARES_EBADRESP; + return Just(ARES_EBADRESP); } unsigned char* buf = response->buf.data; @@ -1352,19 +1487,20 @@ int SrvTraits::Parse( Context::Scope context_scope(env->context()); Local srv_records = Array::New(env->isolate()); - int status = ParseSrvReply(env, buf, len, srv_records); - if (status != ARES_SUCCESS) - return status; + int status; + if (!ParseSrvReply(env, buf, len, srv_records).To(&status)) { + return Nothing(); + } + if (status != ARES_SUCCESS) return Just(status); wrap->CallOnComplete(srv_records); - return ARES_SUCCESS; + return Just(ARES_SUCCESS); } -int PtrTraits::Parse( - QueryPtrWrap* wrap, - const std::unique_ptr& response) { +Maybe PtrTraits::Parse(QueryPtrWrap* wrap, + const std::unique_ptr& response) { if (response->is_host) [[unlikely]] { - return ARES_EBADRESP; + return Just(ARES_EBADRESP); } unsigned char* buf = response->buf.data; int len = response->buf.size; @@ -1376,19 +1512,22 @@ int PtrTraits::Parse( int type = ns_t_ptr; Local aliases = Array::New(env->isolate()); - int status = ParseGeneralReply(env, buf, len, &type, aliases); - if (status != ARES_SUCCESS) - return status; + int status; + if (!ParseGeneralReply(env, buf, len, &type, aliases).To(&status)) { + return Nothing(); + } + if (status != ARES_SUCCESS) { + return Just(status); + } wrap->CallOnComplete(aliases); - return ARES_SUCCESS; + return Just(ARES_SUCCESS); } -int NaptrTraits::Parse( - QueryNaptrWrap* wrap, - const std::unique_ptr& response) { +Maybe NaptrTraits::Parse(QueryNaptrWrap* wrap, + const std::unique_ptr& response) { if (response->is_host) [[unlikely]] { - return ARES_EBADRESP; + return Just(ARES_EBADRESP); } unsigned char* buf = response->buf.data; int len = response->buf.size; @@ -1398,19 +1537,22 @@ int NaptrTraits::Parse( Context::Scope context_scope(env->context()); Local naptr_records = Array::New(env->isolate()); - int status = ParseNaptrReply(env, buf, len, naptr_records); - if (status != ARES_SUCCESS) - return status; + int status; + if (!ParseNaptrReply(env, buf, len, naptr_records).To(&status)) { + return Nothing(); + } + if (status != ARES_SUCCESS) { + return Just(status); + } wrap->CallOnComplete(naptr_records); - return ARES_SUCCESS; + return Just(ARES_SUCCESS); } -int SoaTraits::Parse( - QuerySoaWrap* wrap, - const std::unique_ptr& response) { +Maybe SoaTraits::Parse(QuerySoaWrap* wrap, + const std::unique_ptr& response) { if (response->is_host) [[unlikely]] { - return ARES_EBADRESP; + return Just(ARES_EBADRESP); } unsigned char* buf = response->buf.data; int len = response->buf.size; @@ -1422,42 +1564,55 @@ int SoaTraits::Parse( ares_soa_reply* soa_out; int status = ares_parse_soa_reply(buf, len, &soa_out); - if (status != ARES_SUCCESS) - return status; + if (status != ARES_SUCCESS) return Just(status); Local soa_record = Object::New(env->isolate()); - soa_record->Set(env->context(), - env->nsname_string(), - OneByteString(env->isolate(), soa_out->nsname)).Check(); - soa_record->Set(env->context(), - env->hostmaster_string(), - OneByteString(env->isolate(), soa_out->hostmaster)).Check(); - soa_record->Set(env->context(), - env->serial_string(), - Integer::NewFromUnsigned( - env->isolate(), soa_out->serial)).Check(); - soa_record->Set(env->context(), - env->refresh_string(), - Integer::New(env->isolate(), soa_out->refresh)).Check(); - soa_record->Set(env->context(), - env->retry_string(), - Integer::New(env->isolate(), soa_out->retry)).Check(); - soa_record->Set(env->context(), - env->expire_string(), - Integer::New(env->isolate(), soa_out->expire)).Check(); - soa_record->Set(env->context(), - env->minttl_string(), - Integer::NewFromUnsigned( - env->isolate(), soa_out->minttl)).Check(); + if (soa_record + ->Set(env->context(), + env->nsname_string(), + OneByteString(env->isolate(), soa_out->nsname)) + .IsNothing() || + soa_record + ->Set(env->context(), + env->hostmaster_string(), + OneByteString(env->isolate(), soa_out->hostmaster)) + .IsNothing() || + soa_record + ->Set(env->context(), + env->serial_string(), + Integer::NewFromUnsigned(env->isolate(), soa_out->serial)) + .IsNothing() || + soa_record + ->Set(env->context(), + env->refresh_string(), + Integer::New(env->isolate(), soa_out->refresh)) + .IsNothing() || + soa_record + ->Set(env->context(), + env->retry_string(), + Integer::New(env->isolate(), soa_out->retry)) + .IsNothing() || + soa_record + ->Set(env->context(), + env->expire_string(), + Integer::New(env->isolate(), soa_out->expire)) + .IsNothing() || + soa_record + ->Set(env->context(), + env->minttl_string(), + Integer::NewFromUnsigned(env->isolate(), soa_out->minttl)) + .IsNothing()) { + return Nothing(); + } ares_free_data(soa_out); wrap->CallOnComplete(soa_record); - return ARES_SUCCESS; + return Just(ARES_SUCCESS); } -int ReverseTraits::Send(GetHostByAddrWrap* wrap, const char* name) { +int ReverseTraits::Send(QueryReverseWrap* wrap, const char* name) { int length, family; char address_buffer[sizeof(struct in6_addr)]; @@ -1476,29 +1631,31 @@ int ReverseTraits::Send(GetHostByAddrWrap* wrap, const char* name) { "name", TRACE_STR_COPY(name), "family", family == AF_INET ? "ipv4" : "ipv6"); - ares_gethostbyaddr( - wrap->channel()->cares_channel(), - address_buffer, - length, - family, - GetHostByAddrWrap::Callback, - wrap->MakeCallbackPointer()); + ares_gethostbyaddr(wrap->channel()->cares_channel(), + address_buffer, + length, + family, + QueryReverseWrap::Callback, + wrap->MakeCallbackPointer()); return ARES_SUCCESS; } -int ReverseTraits::Parse( - GetHostByAddrWrap* wrap, - const std::unique_ptr& response) { +Maybe ReverseTraits::Parse(QueryReverseWrap* wrap, + const std::unique_ptr& response) { if (!response->is_host) [[unlikely]] { - return ARES_EBADRESP; + return Just(ARES_EBADRESP); } struct hostent* host = response->host.get(); Environment* env = wrap->env(); HandleScope handle_scope(env->isolate()); Context::Scope context_scope(env->context()); - wrap->CallOnComplete(HostentToNames(env, host)); - return ARES_SUCCESS; + Local names; + if (!HostentToNames(env, host).ToLocal(&names)) { + return Nothing(); + } + wrap->CallOnComplete(names); + return Just(ARES_SUCCESS); } namespace { @@ -2031,37 +2188,15 @@ void Initialize(Local target, SetMethod(context, target, "strerror", StrError); - target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET"), - Integer::New(env->isolate(), AF_INET)).Check(); - target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET6"), - Integer::New(env->isolate(), AF_INET6)).Check(); - target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), - "AF_UNSPEC"), - Integer::New(env->isolate(), AF_UNSPEC)).Check(); - target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), - "AI_ADDRCONFIG"), - Integer::New(env->isolate(), AI_ADDRCONFIG)).Check(); - target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), - "AI_ALL"), - Integer::New(env->isolate(), AI_ALL)).Check(); - target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), - "AI_V4MAPPED"), - Integer::New(env->isolate(), AI_V4MAPPED)).Check(); - target - ->Set(env->context(), - FIXED_ONE_BYTE_STRING(env->isolate(), "DNS_ORDER_VERBATIM"), - Integer::New(env->isolate(), DNS_ORDER_VERBATIM)) - .Check(); - target - ->Set(env->context(), - FIXED_ONE_BYTE_STRING(env->isolate(), "DNS_ORDER_IPV4_FIRST"), - Integer::New(env->isolate(), DNS_ORDER_IPV4_FIRST)) - .Check(); - target - ->Set(env->context(), - FIXED_ONE_BYTE_STRING(env->isolate(), "DNS_ORDER_IPV6_FIRST"), - Integer::New(env->isolate(), DNS_ORDER_IPV6_FIRST)) - .Check(); + NODE_DEFINE_CONSTANT(target, AF_INET); + NODE_DEFINE_CONSTANT(target, AF_INET6); + NODE_DEFINE_CONSTANT(target, AF_UNSPEC); + NODE_DEFINE_CONSTANT(target, AI_ADDRCONFIG); + NODE_DEFINE_CONSTANT(target, AI_ALL); + NODE_DEFINE_CONSTANT(target, AI_V4MAPPED); + NODE_DEFINE_CONSTANT(target, DNS_ORDER_VERBATIM); + NODE_DEFINE_CONSTANT(target, DNS_ORDER_IPV4_FIRST); + NODE_DEFINE_CONSTANT(target, DNS_ORDER_IPV6_FIRST); Local aiw = BaseObject::MakeLazilyInitializedJSTemplate(env); @@ -2084,21 +2219,10 @@ void Initialize(Local target, ChannelWrap::kInternalFieldCount); channel_wrap->Inherit(AsyncWrap::GetConstructorTemplate(env)); - SetProtoMethod(isolate, channel_wrap, "queryAny", Query); - SetProtoMethod(isolate, channel_wrap, "queryA", Query); - SetProtoMethod(isolate, channel_wrap, "queryAaaa", Query); - SetProtoMethod(isolate, channel_wrap, "queryCaa", Query); - SetProtoMethod(isolate, channel_wrap, "queryCname", Query); - SetProtoMethod(isolate, channel_wrap, "queryMx", Query); - SetProtoMethod(isolate, channel_wrap, "queryNs", Query); - SetProtoMethod(isolate, channel_wrap, "queryTlsa", Query); - SetProtoMethod(isolate, channel_wrap, "queryTxt", Query); - SetProtoMethod(isolate, channel_wrap, "querySrv", Query); - SetProtoMethod(isolate, channel_wrap, "queryPtr", Query); - SetProtoMethod(isolate, channel_wrap, "queryNaptr", Query); - SetProtoMethod(isolate, channel_wrap, "querySoa", Query); - SetProtoMethod( - isolate, channel_wrap, "getHostByAddr", Query); +#define V(Name, _, JS) \ + SetProtoMethod(isolate, channel_wrap, #JS, Query); + QUERY_TYPES(V) +#undef V SetProtoMethodNoSideEffect(isolate, channel_wrap, "getServers", GetServers); SetProtoMethod(isolate, channel_wrap, "setServers", SetServers); @@ -2116,20 +2240,9 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { registry->Register(StrError); registry->Register(ChannelWrap::New); - registry->Register(Query); - registry->Register(Query); - registry->Register(Query); - registry->Register(Query); - registry->Register(Query); - registry->Register(Query); - registry->Register(Query); - registry->Register(Query); - registry->Register(Query); - registry->Register(Query); - registry->Register(Query); - registry->Register(Query); - registry->Register(Query); - registry->Register(Query); +#define V(Name, _, __) registry->Register(Query); + QUERY_TYPES(V) +#undef V registry->Register(GetServers); registry->Register(SetServers); diff --git a/src/cares_wrap.h b/src/cares_wrap.h index 6703a5fee3d529..081c8e0217a70f 100644 --- a/src/cares_wrap.h +++ b/src/cares_wrap.h @@ -284,7 +284,9 @@ class QueryWrap final : public AsyncWrap { if (status != ARES_SUCCESS) return ParseError(status); - status = Traits::Parse(this, response_data_); + if (!Traits::Parse(this, response_data_).To(&status)) { + return ParseError(ARES_ECANCELLED); + } if (status != ARES_SUCCESS) ParseError(status); @@ -404,132 +406,38 @@ class QueryWrap final : public AsyncWrap { QueryWrap** callback_ptr_ = nullptr; }; -struct AnyTraits final { - static constexpr const char* name = "resolveAny"; - static int Send(QueryWrap* wrap, const char* name); - static int Parse( - QueryWrap* wrap, - const std::unique_ptr& response); -}; - -struct ATraits final { - static constexpr const char* name = "resolve4"; - static int Send(QueryWrap* wrap, const char* name); - static int Parse( - QueryWrap* wrap, - const std::unique_ptr& response); -}; - -struct AaaaTraits final { - static constexpr const char* name = "resolve6"; - static int Send(QueryWrap* wrap, const char* name); - static int Parse( - QueryWrap* wrap, - const std::unique_ptr& response); -}; - -struct CaaTraits final { - static constexpr const char* name = "resolveCaa"; - static int Send(QueryWrap* wrap, const char* name); - static int Parse( - QueryWrap* wrap, - const std::unique_ptr& response); -}; - -struct CnameTraits final { - static constexpr const char* name = "resolveCname"; - static int Send(QueryWrap* wrap, const char* name); - static int Parse( - QueryWrap* wrap, - const std::unique_ptr& response); -}; - -struct MxTraits final { - static constexpr const char* name = "resolveMx"; - static int Send(QueryWrap* wrap, const char* name); - static int Parse( - QueryWrap* wrap, - const std::unique_ptr& response); -}; - -struct NsTraits final { - static constexpr const char* name = "resolveNs"; - static int Send(QueryWrap* wrap, const char* name); - static int Parse( - QueryWrap* wrap, - const std::unique_ptr& response); -}; - -struct TlsaTraits final { - static constexpr const char* name = "resolveTlsa"; - static int Send(QueryWrap* wrap, const char* name); - static int Parse(QueryWrap* wrap, - const std::unique_ptr& response); -}; - -struct TxtTraits final { - static constexpr const char* name = "resolveTxt"; - static int Send(QueryWrap* wrap, const char* name); - static int Parse( - QueryWrap* wrap, - const std::unique_ptr& response); -}; - -struct SrvTraits final { - static constexpr const char* name = "resolveSrv"; - static int Send(QueryWrap* wrap, const char* name); - static int Parse( - QueryWrap* wrap, - const std::unique_ptr& response); -}; - -struct PtrTraits final { - static constexpr const char* name = "resolvePtr"; - static int Send(QueryWrap* wrap, const char* name); - static int Parse( - QueryWrap* wrap, - const std::unique_ptr& response); -}; - -struct NaptrTraits final { - static constexpr const char* name = "resolveNaptr"; - static int Send(QueryWrap* wrap, const char* name); - static int Parse( - QueryWrap* wrap, - const std::unique_ptr& response); -}; - -struct SoaTraits final { - static constexpr const char* name = "resolveSoa"; - static int Send(QueryWrap* wrap, const char* name); - static int Parse( - QueryWrap* wrap, - const std::unique_ptr& response); -}; - -struct ReverseTraits final { - static constexpr const char* name = "reverse"; - static int Send(QueryWrap* wrap, const char* name); - static int Parse( - QueryWrap* wrap, - const std::unique_ptr& response); -}; - -using QueryAnyWrap = QueryWrap; -using QueryAWrap = QueryWrap; -using QueryAaaaWrap = QueryWrap; -using QueryCaaWrap = QueryWrap; -using QueryCnameWrap = QueryWrap; -using QueryMxWrap = QueryWrap; -using QueryNsWrap = QueryWrap; -using QueryTlsaWrap = QueryWrap; -using QueryTxtWrap = QueryWrap; -using QuerySrvWrap = QueryWrap; -using QueryPtrWrap = QueryWrap; -using QueryNaptrWrap = QueryWrap; -using QuerySoaWrap = QueryWrap; -using GetHostByAddrWrap = QueryWrap; - +#define QUERY_TYPES(V) \ + V(Reverse, reverse, getHostByAddr) \ + V(A, resolve4, queryA) \ + V(Any, resolveAny, queryAny) \ + V(Aaaa, resolve6, queryAaaa) \ + V(Caa, resolveCaa, queryCaa) \ + V(Cname, resolveCname, queryCname) \ + V(Mx, resolveMx, queryMx) \ + V(Naptr, resolveNaptr, queryNaptr) \ + V(Ns, resolveNs, queryNs) \ + V(Ptr, resolvePtr, queryPtr) \ + V(Srv, resolveSrv, querySrv) \ + V(Soa, resolveSoa, querySoa) \ + V(Tlsa, resolveTlsa, queryTlsa) \ + V(Txt, resolveTxt, queryTxt) + +// All query type handlers share the same basic structure, so we can simplify +// the code a bit by using a macro to define that structure. +#define TYPE_TRAITS(Name, label) \ + struct Name##Traits final { \ + static constexpr const char* name = #label; \ + static int Send(QueryWrap* wrap, const char* name); \ + static v8::Maybe Parse( \ + QueryWrap* wrap, \ + const std::unique_ptr& response); \ + }; \ + using Query##Name##Wrap = QueryWrap; + +#define V(NAME, LABEL, _) TYPE_TRAITS(NAME, LABEL) +QUERY_TYPES(V) +#undef V +#undef TYPE_TRAITS } // namespace cares_wrap } // namespace node