@@ -386,6 +386,69 @@ struct CaresAsyncData {
386
386
uv_async_t async_handle;
387
387
};
388
388
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
+
389
452
class QueryWrap : public AsyncWrap {
390
453
public:
391
454
QueryWrap (Environment* env, Local<Object> req_wrap_obj)
@@ -417,6 +480,13 @@ class QueryWrap : public AsyncWrap {
417
480
return static_cast <void *>(this );
418
481
}
419
482
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
+
420
490
static void CaresAsyncClose (uv_handle_t * handle) {
421
491
uv_async_t * async = reinterpret_cast <uv_async_t *>(handle);
422
492
auto data = static_cast <struct CaresAsyncData *>(async->data );
@@ -466,6 +536,7 @@ class QueryWrap : public AsyncWrap {
466
536
uv_async_t * async_handle = &data->async_handle ;
467
537
uv_async_init (wrap->env ()->event_loop (), async_handle, CaresAsyncCb);
468
538
539
+ wrap->env ()->set_cares_query_last_ok (status != ARES_ECONNREFUSED);
469
540
async_handle->data = data;
470
541
uv_async_send (async_handle);
471
542
}
@@ -489,6 +560,7 @@ class QueryWrap : public AsyncWrap {
489
560
uv_async_t * async_handle = &data->async_handle ;
490
561
uv_async_init (wrap->env ()->event_loop (), async_handle, CaresAsyncCb);
491
562
563
+ wrap->env ()->set_cares_query_last_ok (status != ARES_ECONNREFUSED);
492
564
async_handle->data = data;
493
565
uv_async_send (async_handle);
494
566
}
@@ -533,12 +605,7 @@ class QueryAWrap: public QueryWrap {
533
605
}
534
606
535
607
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 ());
542
609
return 0 ;
543
610
}
544
611
@@ -581,12 +648,7 @@ class QueryAaaaWrap: public QueryWrap {
581
648
}
582
649
583
650
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 ());
590
652
return 0 ;
591
653
}
592
654
@@ -629,12 +691,7 @@ class QueryCnameWrap: public QueryWrap {
629
691
}
630
692
631
693
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 ());
638
695
return 0 ;
639
696
}
640
697
@@ -670,12 +727,7 @@ class QueryMxWrap: public QueryWrap {
670
727
}
671
728
672
729
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 ());
679
731
return 0 ;
680
732
}
681
733
@@ -721,12 +773,7 @@ class QueryNsWrap: public QueryWrap {
721
773
}
722
774
723
775
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 ());
730
777
return 0 ;
731
778
}
732
779
@@ -759,12 +806,7 @@ class QueryTxtWrap: public QueryWrap {
759
806
}
760
807
761
808
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 ());
768
810
return 0 ;
769
811
}
770
812
@@ -816,12 +858,7 @@ class QuerySrvWrap: public QueryWrap {
816
858
}
817
859
818
860
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 ());
825
862
return 0 ;
826
863
}
827
864
@@ -872,12 +909,7 @@ class QueryPtrWrap: public QueryWrap {
872
909
}
873
910
874
911
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 ());
881
913
return 0 ;
882
914
}
883
915
@@ -915,12 +947,7 @@ class QueryNaptrWrap: public QueryWrap {
915
947
}
916
948
917
949
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 ());
924
951
return 0 ;
925
952
}
926
953
@@ -979,12 +1006,7 @@ class QuerySoaWrap: public QueryWrap {
979
1006
}
980
1007
981
1008
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 ());
988
1010
return 0 ;
989
1011
}
990
1012
@@ -1445,6 +1467,9 @@ void SetServers(const FunctionCallbackInfo<Value>& args) {
1445
1467
1446
1468
delete[] servers;
1447
1469
1470
+ if (err == ARES_SUCCESS)
1471
+ env->set_cares_is_servers_default (false );
1472
+
1448
1473
args.GetReturnValue ().Set (err);
1449
1474
}
1450
1475
@@ -1479,20 +1504,7 @@ void Initialize(Local<Object> target,
1479
1504
if (r != ARES_SUCCESS)
1480
1505
return env->ThrowError (ToErrorCodeString (r));
1481
1506
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);
1496
1508
1497
1509
/* Initialize the timeout timer. The timer won't be started until the */
1498
1510
/* first socket is opened. */
0 commit comments