@@ -386,6 +386,69 @@ struct CaresAsyncData {
386386 uv_async_t async_handle;
387387};
388388
389+ void SetupCaresChannel (Environment* env) {
390+ struct ares_options options;
391+ memset (&options, 0 , sizeof (options));
392+ options.flags = ARES_FLAG_NOCHECKRESP;
393+ options.sock_state_cb = ares_sockstate_cb;
394+ options.sock_state_cb_data = env;
395+
396+ /* We do the call to ares_init_option for caller. */
397+ int r = ares_init_options (env->cares_channel_ptr (),
398+ &options,
399+ ARES_OPT_FLAGS | ARES_OPT_SOCK_STATE_CB);
400+
401+ if (r != ARES_SUCCESS) {
402+ ares_library_cleanup ();
403+ return env->ThrowError (ToErrorCodeString (r));
404+ }
405+ }
406+
407+
408+ /* *
409+ * This function is to check whether current servers are fallback servers
410+ * when cares initialized.
411+ *
412+ * The fallback servers of cares is [ "127.0.0.1" ] with no user additional
413+ * setting.
414+ */
415+ void AresEnsureServers (Environment* env) {
416+ /* if last query is OK or servers are set by user self, do not check */
417+ if (env->cares_query_last_ok () || !env->cares_is_servers_default ()) {
418+ return ;
419+ }
420+
421+ ares_channel channel = env->cares_channel ();
422+ ares_addr_node* servers = nullptr ;
423+
424+ ares_get_servers (channel, &servers);
425+
426+ /* if no server or multi-servers, ignore */
427+ if (servers == nullptr ) return ;
428+ if (servers->next != nullptr ) {
429+ ares_free_data (servers);
430+ env->set_cares_is_servers_default (false );
431+ return ;
432+ }
433+
434+ /* if the only server is not 127.0.0.1, ignore */
435+ if (servers[0 ].family != AF_INET ||
436+ servers[0 ].addr .addr4 .s_addr != htonl (INADDR_LOOPBACK)) {
437+ ares_free_data (servers);
438+ env->set_cares_is_servers_default (false );
439+ return ;
440+ }
441+
442+ ares_free_data (servers);
443+ servers = nullptr ;
444+
445+ /* destroy channel and reset channel */
446+ ares_destroy (channel);
447+
448+ SetupCaresChannel (env);
449+ }
450+
451+
389452class QueryWrap : public AsyncWrap {
390453 public:
391454 QueryWrap (Environment* env, Local<Object> req_wrap_obj)
@@ -417,6 +480,13 @@ class QueryWrap : public AsyncWrap {
417480 return static_cast <void *>(this );
418481 }
419482
483+ static void AresQuery (Environment* env, const char * name,
484+ int dnsclass, int type, ares_callback callback,
485+ void * arg) {
486+ AresEnsureServers (env);
487+ ares_query (env->cares_channel (), name, dnsclass, type, callback, arg);
488+ }
489+
420490 static void CaresAsyncClose (uv_handle_t * handle) {
421491 uv_async_t * async = reinterpret_cast <uv_async_t *>(handle);
422492 auto data = static_cast <struct CaresAsyncData *>(async->data );
@@ -466,6 +536,7 @@ class QueryWrap : public AsyncWrap {
466536 uv_async_t * async_handle = &data->async_handle ;
467537 uv_async_init (wrap->env ()->event_loop (), async_handle, CaresAsyncCb);
468538
539+ wrap->env ()->set_cares_query_last_ok (status != ARES_ECONNREFUSED);
469540 async_handle->data = data;
470541 uv_async_send (async_handle);
471542 }
@@ -489,6 +560,7 @@ class QueryWrap : public AsyncWrap {
489560 uv_async_t * async_handle = &data->async_handle ;
490561 uv_async_init (wrap->env ()->event_loop (), async_handle, CaresAsyncCb);
491562
563+ wrap->env ()->set_cares_query_last_ok (status != ARES_ECONNREFUSED);
492564 async_handle->data = data;
493565 uv_async_send (async_handle);
494566 }
@@ -533,12 +605,7 @@ class QueryAWrap: public QueryWrap {
533605 }
534606
535607 int Send (const char * name) override {
536- ares_query (env ()->cares_channel (),
537- name,
538- ns_c_in,
539- ns_t_a,
540- Callback,
541- GetQueryArg ());
608+ AresQuery (env (), name, ns_c_in, ns_t_a, Callback, GetQueryArg ());
542609 return 0 ;
543610 }
544611
@@ -581,12 +648,7 @@ class QueryAaaaWrap: public QueryWrap {
581648 }
582649
583650 int Send (const char * name) override {
584- ares_query (env ()->cares_channel (),
585- name,
586- ns_c_in,
587- ns_t_aaaa,
588- Callback,
589- GetQueryArg ());
651+ AresQuery (env (), name, ns_c_in, ns_t_aaaa, Callback, GetQueryArg ());
590652 return 0 ;
591653 }
592654
@@ -629,12 +691,7 @@ class QueryCnameWrap: public QueryWrap {
629691 }
630692
631693 int Send (const char * name) override {
632- ares_query (env ()->cares_channel (),
633- name,
634- ns_c_in,
635- ns_t_cname,
636- Callback,
637- GetQueryArg ());
694+ AresQuery (env (), name, ns_c_in, ns_t_cname, Callback, GetQueryArg ());
638695 return 0 ;
639696 }
640697
@@ -670,12 +727,7 @@ class QueryMxWrap: public QueryWrap {
670727 }
671728
672729 int Send (const char * name) override {
673- ares_query (env ()->cares_channel (),
674- name,
675- ns_c_in,
676- ns_t_mx,
677- Callback,
678- GetQueryArg ());
730+ AresQuery (env (), name, ns_c_in, ns_t_mx, Callback, GetQueryArg ());
679731 return 0 ;
680732 }
681733
@@ -721,12 +773,7 @@ class QueryNsWrap: public QueryWrap {
721773 }
722774
723775 int Send (const char * name) override {
724- ares_query (env ()->cares_channel (),
725- name,
726- ns_c_in,
727- ns_t_ns,
728- Callback,
729- GetQueryArg ());
776+ AresQuery (env (), name, ns_c_in, ns_t_ns, Callback, GetQueryArg ());
730777 return 0 ;
731778 }
732779
@@ -759,12 +806,7 @@ class QueryTxtWrap: public QueryWrap {
759806 }
760807
761808 int Send (const char * name) override {
762- ares_query (env ()->cares_channel (),
763- name,
764- ns_c_in,
765- ns_t_txt,
766- Callback,
767- GetQueryArg ());
809+ AresQuery (env (), name, ns_c_in, ns_t_txt, Callback, GetQueryArg ());
768810 return 0 ;
769811 }
770812
@@ -816,12 +858,7 @@ class QuerySrvWrap: public QueryWrap {
816858 }
817859
818860 int Send (const char * name) override {
819- ares_query (env ()->cares_channel (),
820- name,
821- ns_c_in,
822- ns_t_srv,
823- Callback,
824- GetQueryArg ());
861+ AresQuery (env (), name, ns_c_in, ns_t_srv, Callback, GetQueryArg ());
825862 return 0 ;
826863 }
827864
@@ -872,12 +909,7 @@ class QueryPtrWrap: public QueryWrap {
872909 }
873910
874911 int Send (const char * name) override {
875- ares_query (env ()->cares_channel (),
876- name,
877- ns_c_in,
878- ns_t_ptr,
879- Callback,
880- GetQueryArg ());
912+ AresQuery (env (), name, ns_c_in, ns_t_ptr, Callback, GetQueryArg ());
881913 return 0 ;
882914 }
883915
@@ -915,12 +947,7 @@ class QueryNaptrWrap: public QueryWrap {
915947 }
916948
917949 int Send (const char * name) override {
918- ares_query (env ()->cares_channel (),
919- name,
920- ns_c_in,
921- ns_t_naptr,
922- Callback,
923- GetQueryArg ());
950+ AresQuery (env (), name, ns_c_in, ns_t_naptr, Callback, GetQueryArg ());
924951 return 0 ;
925952 }
926953
@@ -979,12 +1006,7 @@ class QuerySoaWrap: public QueryWrap {
9791006 }
9801007
9811008 int Send (const char * name) override {
982- ares_query (env ()->cares_channel (),
983- name,
984- ns_c_in,
985- ns_t_soa,
986- Callback,
987- GetQueryArg ());
1009+ AresQuery (env (), name, ns_c_in, ns_t_soa, Callback, GetQueryArg ());
9881010 return 0 ;
9891011 }
9901012
@@ -1445,6 +1467,9 @@ void SetServers(const FunctionCallbackInfo<Value>& args) {
14451467
14461468 delete[] servers;
14471469
1470+ if (err == ARES_SUCCESS)
1471+ env->set_cares_is_servers_default (false );
1472+
14481473 args.GetReturnValue ().Set (err);
14491474}
14501475
@@ -1479,20 +1504,7 @@ void Initialize(Local<Object> target,
14791504 if (r != ARES_SUCCESS)
14801505 return env->ThrowError (ToErrorCodeString (r));
14811506
1482- struct ares_options options;
1483- memset (&options, 0 , sizeof (options));
1484- options.flags = ARES_FLAG_NOCHECKRESP;
1485- options.sock_state_cb = ares_sockstate_cb;
1486- options.sock_state_cb_data = env;
1487-
1488- /* We do the call to ares_init_option for caller. */
1489- r = ares_init_options (env->cares_channel_ptr (),
1490- &options,
1491- ARES_OPT_FLAGS | ARES_OPT_SOCK_STATE_CB);
1492- if (r != ARES_SUCCESS) {
1493- ares_library_cleanup ();
1494- return env->ThrowError (ToErrorCodeString (r));
1495- }
1507+ SetupCaresChannel (env);
14961508
14971509 /* Initialize the timeout timer. The timer won't be started until the */
14981510 /* first socket is opened. */
0 commit comments