@@ -372,6 +372,69 @@ struct CaresAsyncData {
372372 uv_async_t async_handle;
373373};
374374
375+ void SetupCaresChannel (Environment* env) {
376+ struct ares_options options;
377+ memset (&options, 0 , sizeof (options));
378+ options.flags = ARES_FLAG_NOCHECKRESP;
379+ options.sock_state_cb = ares_sockstate_cb;
380+ options.sock_state_cb_data = env;
381+
382+ /* We do the call to ares_init_option for caller. */
383+ int r = ares_init_options (env->cares_channel_ptr (),
384+ &options,
385+ ARES_OPT_FLAGS | ARES_OPT_SOCK_STATE_CB);
386+
387+ if (r != ARES_SUCCESS) {
388+ ares_library_cleanup ();
389+ return env->ThrowError (ToErrorCodeString (r));
390+ }
391+ }
392+
393+
394+ /* *
395+ * This function is to check whether current servers are fallback servers
396+ * when cares initialized.
397+ *
398+ * The fallback servers of cares is [ "127.0.0.1" ] with no user additional
399+ * setting.
400+ */
401+ void AresEnsureServers (Environment* env) {
402+ /* if last query is OK or servers are set by user self, do not check */
403+ if (env->cares_query_last_ok () || !env->cares_is_servers_default ()) {
404+ return ;
405+ }
406+
407+ ares_channel channel = env->cares_channel ();
408+ ares_addr_node* servers = nullptr ;
409+
410+ ares_get_servers (channel, &servers);
411+
412+ /* if no server or multi-servers, ignore */
413+ if (servers == nullptr ) return ;
414+ if (servers->next != nullptr ) {
415+ ares_free_data (servers);
416+ env->set_cares_is_servers_default (false );
417+ return ;
418+ }
419+
420+ /* if the only server is not 127.0.0.1, ignore */
421+ if (servers[0 ].family != AF_INET ||
422+ servers[0 ].addr .addr4 .s_addr != htonl (INADDR_LOOPBACK)) {
423+ ares_free_data (servers);
424+ env->set_cares_is_servers_default (false );
425+ return ;
426+ }
427+
428+ ares_free_data (servers);
429+ servers = nullptr ;
430+
431+ /* destroy channel and reset channel */
432+ ares_destroy (channel);
433+
434+ SetupCaresChannel (env);
435+ }
436+
437+
375438class QueryWrap : public AsyncWrap {
376439 public:
377440 QueryWrap (Environment* env, Local<Object> req_wrap_obj)
@@ -402,6 +465,13 @@ class QueryWrap : public AsyncWrap {
402465 return static_cast <void *>(this );
403466 }
404467
468+ static void AresQuery (Environment* env, const char * name,
469+ int dnsclass, int type, ares_callback callback,
470+ void * arg) {
471+ AresEnsureServers (env);
472+ ares_query (env->cares_channel (), name, dnsclass, type, callback, arg);
473+ }
474+
405475 static void CaresAsyncClose (uv_handle_t * handle) {
406476 uv_async_t * async = reinterpret_cast <uv_async_t *>(handle);
407477 auto data = static_cast <struct CaresAsyncData *>(async->data );
@@ -453,6 +523,7 @@ class QueryWrap : public AsyncWrap {
453523 async_handle,
454524 CaresAsyncCb));
455525
526+ wrap->env ()->set_cares_query_last_ok (status != ARES_ECONNREFUSED);
456527 async_handle->data = data;
457528 uv_async_send (async_handle);
458529 }
@@ -478,6 +549,7 @@ class QueryWrap : public AsyncWrap {
478549 async_handle,
479550 CaresAsyncCb));
480551
552+ wrap->env ()->set_cares_query_last_ok (status != ARES_ECONNREFUSED);
481553 async_handle->data = data;
482554 uv_async_send (async_handle);
483555 }
@@ -522,12 +594,7 @@ class QueryAWrap: public QueryWrap {
522594 }
523595
524596 int Send (const char * name) override {
525- ares_query (env ()->cares_channel (),
526- name,
527- ns_c_in,
528- ns_t_a,
529- Callback,
530- GetQueryArg ());
597+ AresQuery (env (), name, ns_c_in, ns_t_a, Callback, GetQueryArg ());
531598 return 0 ;
532599 }
533600
@@ -570,12 +637,7 @@ class QueryAaaaWrap: public QueryWrap {
570637 }
571638
572639 int Send (const char * name) override {
573- ares_query (env ()->cares_channel (),
574- name,
575- ns_c_in,
576- ns_t_aaaa,
577- Callback,
578- GetQueryArg ());
640+ AresQuery (env (), name, ns_c_in, ns_t_aaaa, Callback, GetQueryArg ());
579641 return 0 ;
580642 }
581643
@@ -618,12 +680,7 @@ class QueryCnameWrap: public QueryWrap {
618680 }
619681
620682 int Send (const char * name) override {
621- ares_query (env ()->cares_channel (),
622- name,
623- ns_c_in,
624- ns_t_cname,
625- Callback,
626- GetQueryArg ());
683+ AresQuery (env (), name, ns_c_in, ns_t_cname, Callback, GetQueryArg ());
627684 return 0 ;
628685 }
629686
@@ -659,12 +716,7 @@ class QueryMxWrap: public QueryWrap {
659716 }
660717
661718 int Send (const char * name) override {
662- ares_query (env ()->cares_channel (),
663- name,
664- ns_c_in,
665- ns_t_mx,
666- Callback,
667- GetQueryArg ());
719+ AresQuery (env (), name, ns_c_in, ns_t_mx, Callback, GetQueryArg ());
668720 return 0 ;
669721 }
670722
@@ -710,12 +762,7 @@ class QueryNsWrap: public QueryWrap {
710762 }
711763
712764 int Send (const char * name) override {
713- ares_query (env ()->cares_channel (),
714- name,
715- ns_c_in,
716- ns_t_ns,
717- Callback,
718- GetQueryArg ());
765+ AresQuery (env (), name, ns_c_in, ns_t_ns, Callback, GetQueryArg ());
719766 return 0 ;
720767 }
721768
@@ -748,12 +795,7 @@ class QueryTxtWrap: public QueryWrap {
748795 }
749796
750797 int Send (const char * name) override {
751- ares_query (env ()->cares_channel (),
752- name,
753- ns_c_in,
754- ns_t_txt,
755- Callback,
756- GetQueryArg ());
798+ AresQuery (env (), name, ns_c_in, ns_t_txt, Callback, GetQueryArg ());
757799 return 0 ;
758800 }
759801
@@ -805,12 +847,7 @@ class QuerySrvWrap: public QueryWrap {
805847 }
806848
807849 int Send (const char * name) override {
808- ares_query (env ()->cares_channel (),
809- name,
810- ns_c_in,
811- ns_t_srv,
812- Callback,
813- GetQueryArg ());
850+ AresQuery (env (), name, ns_c_in, ns_t_srv, Callback, GetQueryArg ());
814851 return 0 ;
815852 }
816853
@@ -861,12 +898,7 @@ class QueryPtrWrap: public QueryWrap {
861898 }
862899
863900 int Send (const char * name) override {
864- ares_query (env ()->cares_channel (),
865- name,
866- ns_c_in,
867- ns_t_ptr,
868- Callback,
869- GetQueryArg ());
901+ AresQuery (env (), name, ns_c_in, ns_t_ptr, Callback, GetQueryArg ());
870902 return 0 ;
871903 }
872904
@@ -904,12 +936,7 @@ class QueryNaptrWrap: public QueryWrap {
904936 }
905937
906938 int Send (const char * name) override {
907- ares_query (env ()->cares_channel (),
908- name,
909- ns_c_in,
910- ns_t_naptr,
911- Callback,
912- GetQueryArg ());
939+ AresQuery (env (), name, ns_c_in, ns_t_naptr, Callback, GetQueryArg ());
913940 return 0 ;
914941 }
915942
@@ -968,12 +995,7 @@ class QuerySoaWrap: public QueryWrap {
968995 }
969996
970997 int Send (const char * name) override {
971- ares_query (env ()->cares_channel (),
972- name,
973- ns_c_in,
974- ns_t_soa,
975- Callback,
976- GetQueryArg ());
998+ AresQuery (env (), name, ns_c_in, ns_t_soa, Callback, GetQueryArg ());
977999 return 0 ;
9781000 }
9791001
@@ -1434,6 +1456,9 @@ static void SetServers(const FunctionCallbackInfo<Value>& args) {
14341456
14351457 delete[] servers;
14361458
1459+ if (err == ARES_SUCCESS)
1460+ env->set_cares_is_servers_default (false );
1461+
14371462 args.GetReturnValue ().Set (err);
14381463}
14391464
@@ -1468,20 +1493,7 @@ static void Initialize(Local<Object> target,
14681493 if (r != ARES_SUCCESS)
14691494 return env->ThrowError (ToErrorCodeString (r));
14701495
1471- struct ares_options options;
1472- memset (&options, 0 , sizeof (options));
1473- options.flags = ARES_FLAG_NOCHECKRESP;
1474- options.sock_state_cb = ares_sockstate_cb;
1475- options.sock_state_cb_data = env;
1476-
1477- /* We do the call to ares_init_option for caller. */
1478- r = ares_init_options (env->cares_channel_ptr (),
1479- &options,
1480- ARES_OPT_FLAGS | ARES_OPT_SOCK_STATE_CB);
1481- if (r != ARES_SUCCESS) {
1482- ares_library_cleanup ();
1483- return env->ThrowError (ToErrorCodeString (r));
1484- }
1496+ SetupCaresChannel (env);
14851497
14861498 /* Initialize the timeout timer. The timer won't be started until the */
14871499 /* first socket is opened. */
0 commit comments