4 个文件变更+136-42
@@ -344,7 +344,7 @@ ares_status_t ares_send_query(ares_server_t *requested_server /* Optional */,
344ares_status_t ares_requeue_query(ares_query_t *query, const ares_timeval_t *now,344ares_status_t ares_requeue_query(ares_query_t *query, const ares_timeval_t *now,
345 ares_status_t status,345 ares_status_t status,
346 ares_bool_t inc_try_count,346 ares_bool_t inc_try_count,
347- const ares_dns_record_t *dnsrec,347+ ares_dns_record_t *dnsrec,
348 ares_array_t **requeue);348 ares_array_t **requeue);
349 349 
350/*! Count the number of labels (dots+1) in a domain */350/*! Count the number of labels (dots+1) in a domain */
@@ -617,10 +617,10 @@ ares_status_t ares_qcache_create(ares_rand_state *rand_state,
617 unsigned int max_ttl,617 unsigned int max_ttl,
618 ares_qcache_t **cache_out);618 ares_qcache_t **cache_out);
619void ares_qcache_flush(ares_qcache_t *cache);619void ares_qcache_flush(ares_qcache_t *cache);
620-ares_status_t ares_qcache_insert(ares_channel_t *channel,620+ares_status_t ares_qcache_insert(ares_channel_t *channel,
621- const ares_timeval_t *now,621+ const ares_timeval_t *now,
622- const ares_query_t *query,622+ const ares_query_t *query,
623- ares_dns_record_t *dnsrec);623+ const ares_dns_record_t *dnsrec);
624ares_status_t ares_qcache_fetch(ares_channel_t *channel,624ares_status_t ares_qcache_fetch(ares_channel_t *channel,
625 const ares_timeval_t *now,625 const ares_timeval_t *now,
626 const ares_dns_record_t *dnsrec,626 const ares_dns_record_t *dnsrec,
@@ -64,7 +64,8 @@ static ares_bool_t same_questions(const ares_query_t *query,
64 const ares_dns_record_t *arec);64 const ares_dns_record_t *arec);
65static void end_query(ares_channel_t *channel, ares_server_t *server,65static void end_query(ares_channel_t *channel, ares_server_t *server,
66 ares_query_t *query, ares_status_t status,66 ares_query_t *query, ares_status_t status,
67- const ares_dns_record_t *dnsrec);67+ ares_dns_record_t *dnsrec,
68+ ares_array_t **requeue);
68 69 
69static void ares_query_remove_from_conn(ares_query_t *query)70static void ares_query_remove_from_conn(ares_query_t *query)
70{71{
@@ -511,16 +512,27 @@ static ares_status_t read_conn_packets(ares_conn_t *conn)
511 return ARES_SUCCESS;512 return ARES_SUCCESS;
512}513}
513 514 
515+typedef enum {
516+ REQUEUE_REQUEUE = 1,
517+ REQUEUE_ENDQUERY = 2
518+} requeue_type_t;
519+ 
514/* Simple data structure to store a query that needs to be requeued with520/* Simple data structure to store a query that needs to be requeued with
515 * optional server */521 * optional server */
516typedef struct {522typedef struct {
517- unsigned short qid;523+ requeue_type_t type; /* type of entry, requeue or endquery */
518- ares_server_t *server; /* optional */524+ unsigned short qid; /* query id */
525+ ares_server_t *server; /* requeue only: optional */
526+ ares_status_t status; /* endquery only */
527+ ares_dns_record_t *dnsrec; /* endquery only: optional */
519} ares_requeue_t;528} ares_requeue_t;
520 529 
521-static ares_status_t ares_append_requeue(ares_array_t **requeue,530+static ares_status_t ares_append_requeue_int(ares_array_t **requeue,
522- ares_query_t *query,531+ requeue_type_t type,
523- ares_server_t *server)532+ ares_query_t *query,
533+ ares_server_t *server,
534+ ares_status_t status,
535+ ares_dns_record_t *dnsrec)
524{536{
525 ares_requeue_t entry;537 ares_requeue_t entry;
526 538 
@@ -533,16 +545,36 @@ static ares_status_t ares_append_requeue(ares_array_t **requeue,
533 545 
534 ares_query_remove_from_conn(query);546 ares_query_remove_from_conn(query);
535 547 
548+ entry.type = type;
536 entry.qid = query->qid;549 entry.qid = query->qid;
537 entry.server = server;550 entry.server = server;
551+ entry.status = status;
552+ entry.dnsrec = dnsrec;
538 return ares_array_insertdata_last(*requeue, &entry);553 return ares_array_insertdata_last(*requeue, &entry);
539}554}
540 555 
556+static ares_status_t ares_append_requeue(ares_array_t **requeue,
557+ ares_query_t *query,
558+ ares_server_t *server)
559+{
560+ return ares_append_requeue_int(requeue, REQUEUE_REQUEUE, query, server, 0,
561+ NULL);
562+}
563+
564+static ares_status_t ares_append_endqueue(ares_array_t **requeue,
565+ ares_query_t *query,
566+ ares_status_t status,
567+ ares_dns_record_t *dnsrec)
568+{
569+ return ares_append_requeue_int(requeue, REQUEUE_ENDQUERY, query, NULL, status,
570+ dnsrec);
571+}
572+ 
541static ares_status_t read_answers(ares_conn_t *conn, const ares_timeval_t *now)573static ares_status_t read_answers(ares_conn_t *conn, const ares_timeval_t *now)
542{574{
543 ares_status_t status;575 ares_status_t status;
544- ares_channel_t *channel = conn->server->channel;576+ ares_channel_t *channel = conn->server->channel;
545- ares_array_t *requeue = NULL;577+ ares_array_t *requeue = NULL;
546 578 
547 /* Process all queued answers */579 /* Process all queued answers */
548 while (1) {580 while (1) {
@@ -602,18 +634,30 @@ cleanup:
602 break;634 break;
603 }635 }
604 636 
605- /* Query disappeared */
606 query = ares_htable_szvp_get_direct(channel->queries_by_qid, entry.qid);637 query = ares_htable_szvp_get_direct(channel->queries_by_qid, entry.qid);
607- if (query == NULL) {
608- continue;
609- }
610 638 
611- internal_status = ares_send_query(entry.server, query, now);639+ if (entry.type == REQUEUE_REQUEUE) {
612- /* We only care about ARES_ENOMEM */640+ /* query disappeared */
613- if (internal_status == ARES_ENOMEM) {641+ if (query == NULL) {
614- status = ARES_ENOMEM;642+ continue;
643+ }
644+ internal_status = ares_send_query(entry.server, query, now);
645+ /* We only care about ARES_ENOMEM */
646+ if (internal_status == ARES_ENOMEM) {
647+ status = ARES_ENOMEM;
648+ }
649+ } else { /* REQUEUE_ENDQUERY */
650+ if (query != NULL) {
651+ query->callback(query->arg, entry.status, query->timeouts, entry.dnsrec);
652+ ares_free_query(query);
653+ }
654+ ares_dns_record_destroy(entry.dnsrec);
615 }655 }
616 }656 }
657+ /* Don't forget to send notification if queue emptied */
658+ if (requeue != NULL) {
659+ ares_queue_notify_empty(channel);
660+ }
617 ares_array_destroy(requeue);661 ares_array_destroy(requeue);
618 662 
619 return status;663 return status;
@@ -669,7 +713,7 @@ static ares_status_t process_timeouts(ares_channel_t *channel,
669 conn = query->conn;713 conn = query->conn;
670 server_increment_failures(conn->server, query->using_tcp);714 server_increment_failures(conn->server, query->using_tcp);
671 status = ares_requeue_query(query, now, ARES_ETIMEOUT, ARES_TRUE, NULL,715 status = ares_requeue_query(query, now, ARES_ETIMEOUT, ARES_TRUE, NULL,
672- NULL);716+ NULL);
673 if (status == ARES_ENOMEM) {717 if (status == ARES_ENOMEM) {
674 goto done;718 goto done;
675 }719 }
@@ -824,7 +868,7 @@ static ares_status_t process_answer(ares_channel_t *channel,
824 if (issue_might_be_edns(query->query, rdnsrec)) {868 if (issue_might_be_edns(query->query, rdnsrec)) {
825 status = rewrite_without_edns(query);869 status = rewrite_without_edns(query);
826 if (status != ARES_SUCCESS) {870 if (status != ARES_SUCCESS) {
827- end_query(channel, server, query, status, NULL);871+ end_query(channel, server, query, status, NULL, NULL);
828 goto cleanup;872 goto cleanup;
829 }873 }
830 874 
@@ -869,7 +913,9 @@ static ares_status_t process_answer(ares_channel_t *channel,
869 }913 }
870 914 
871 server_increment_failures(server, query->using_tcp);915 server_increment_failures(server, query->using_tcp);
872- status = ares_requeue_query(query, now, status, ARES_TRUE, rdnsrec, requeue);916+ status = ares_requeue_query(query, now, status, ARES_TRUE, rdnsrec,
917+ requeue);
918+ rdnsrec = NULL; /* Free'd by ares_requeue_query() */
873 919 
874 if (status != ARES_ENOMEM) {920 if (status != ARES_ENOMEM) {
875 /* Should any of these cause a connection termination?921 /* Should any of these cause a connection termination?
@@ -882,12 +928,11 @@ static ares_status_t process_answer(ares_channel_t *channel,
882 928 
883 /* If cache insertion was successful, it took ownership. We ignore929 /* If cache insertion was successful, it took ownership. We ignore
884 * other cache insertion failures. */930 * other cache insertion failures. */
885- if (ares_qcache_insert(channel, now, query, rdnsrec) == ARES_SUCCESS) {931+ ares_qcache_insert(channel, now, query, rdnsrec);
886- is_cached = ARES_TRUE;
887- }
888 932 
889 server_set_good(server, query->using_tcp);933 server_set_good(server, query->using_tcp);
890- end_query(channel, server, query, ARES_SUCCESS, rdnsrec);934+ end_query(channel, server, query, ARES_SUCCESS, rdnsrec, requeue);
935+ rdnsrec = NULL; /* Free'd by the requeue */
891 936 
892 status = ARES_SUCCESS;937 status = ARES_SUCCESS;
893 938 
@@ -922,7 +967,7 @@ static void handle_conn_error(ares_conn_t *conn, ares_bool_t critical_failure,
922ares_status_t ares_requeue_query(ares_query_t *query, const ares_timeval_t *now,967ares_status_t ares_requeue_query(ares_query_t *query, const ares_timeval_t *now,
923 ares_status_t status,968 ares_status_t status,
924 ares_bool_t inc_try_count,969 ares_bool_t inc_try_count,
925- const ares_dns_record_t *dnsrec,970+ ares_dns_record_t *dnsrec,
926 ares_array_t **requeue)971 ares_array_t **requeue)
927{972{
928 ares_channel_t *channel = query->channel;973 ares_channel_t *channel = query->channel;
@@ -939,6 +984,7 @@ ares_status_t ares_requeue_query(ares_query_t *query, const ares_timeval_t *now,
939 }984 }
940 985 
941 if (query->try_count < max_tries && !query->no_retries) {986 if (query->try_count < max_tries && !query->no_retries) {
987+ ares_dns_record_destroy(dnsrec);
942 if (requeue != NULL) {988 if (requeue != NULL) {
943 return ares_append_requeue(requeue, query, NULL);989 return ares_append_requeue(requeue, query, NULL);
944 }990 }
@@ -950,7 +996,7 @@ ares_status_t ares_requeue_query(ares_query_t *query, const ares_timeval_t *now,
950 query->error_status = ARES_ETIMEOUT;996 query->error_status = ARES_ETIMEOUT;
951 }997 }
952 998 
953- end_query(channel, NULL, query, query->error_status, dnsrec);999+ end_query(channel, NULL, query, query->error_status, dnsrec, requeue);
954 return ARES_ETIMEOUT;1000 return ARES_ETIMEOUT;
955}1001}
956 1002 
@@ -1232,7 +1278,7 @@ ares_status_t ares_send_query(ares_server_t *requested_server,
1232 }1278 }
1233 1279 
1234 if (server == NULL) {1280 if (server == NULL) {
1235- end_query(channel, server, query, ARES_ENOSERVER /* ? */, NULL);1281+ end_query(channel, server, query, ARES_ENOSERVER /* ? */, NULL, NULL);
1236 return ARES_ENOSERVER;1282 return ARES_ENOSERVER;
1237 }1283 }
1238 1284 
@@ -1260,7 +1306,7 @@ ares_status_t ares_send_query(ares_server_t *requested_server,
1260 1306 
1261 /* Anything else is not retryable, likely ENOMEM */1307 /* Anything else is not retryable, likely ENOMEM */
1262 default:1308 default:
1263- end_query(channel, server, query, status, NULL);1309+ end_query(channel, server, query, status, NULL, NULL);
1264 return status;1310 return status;
1265 }1311 }
1266 }1312 }
@@ -1274,7 +1320,7 @@ ares_status_t ares_send_query(ares_server_t *requested_server,
1274 1320 
1275 case ARES_ENOMEM:1321 case ARES_ENOMEM:
1276 /* Not retryable */1322 /* Not retryable */
1277- end_query(channel, server, query, status, NULL);1323+ end_query(channel, server, query, status, NULL, NULL);
1278 return status;1324 return status;
1279 1325 
1280 /* These conditions are retryable as they are server-specific1326 /* These conditions are retryable as they are server-specific
@@ -1309,7 +1355,7 @@ ares_status_t ares_send_query(ares_server_t *requested_server,
1309 ares_slist_insert(channel->queries_by_timeout, query);1355 ares_slist_insert(channel->queries_by_timeout, query);
1310 if (!query->node_queries_by_timeout) {1356 if (!query->node_queries_by_timeout) {
1311 /* LCOV_EXCL_START: OutOfMemory */1357 /* LCOV_EXCL_START: OutOfMemory */
1312- end_query(channel, server, query, ARES_ENOMEM, NULL);1358+ end_query(channel, server, query, ARES_ENOMEM, NULL, NULL);
1313 return ARES_ENOMEM;1359 return ARES_ENOMEM;
1314 /* LCOV_EXCL_STOP */1360 /* LCOV_EXCL_STOP */
1315 }1361 }
@@ -1322,7 +1368,7 @@ ares_status_t ares_send_query(ares_server_t *requested_server,
1322 1368 
1323 if (query->node_queries_to_conn == NULL) {1369 if (query->node_queries_to_conn == NULL) {
1324 /* LCOV_EXCL_START: OutOfMemory */1370 /* LCOV_EXCL_START: OutOfMemory */
1325- end_query(channel, server, query, ARES_ENOMEM, NULL);1371+ end_query(channel, server, query, ARES_ENOMEM, NULL, NULL);
1326 return ARES_ENOMEM;1372 return ARES_ENOMEM;
1327 /* LCOV_EXCL_STOP */1373 /* LCOV_EXCL_STOP */
1328 }1374 }
@@ -1410,7 +1456,7 @@ static void ares_detach_query(ares_query_t *query)
1410 1456 
1411static void end_query(ares_channel_t *channel, ares_server_t *server,1457static void end_query(ares_channel_t *channel, ares_server_t *server,
1412 ares_query_t *query, ares_status_t status,1458 ares_query_t *query, ares_status_t status,
1413- const ares_dns_record_t *dnsrec)1459+ ares_dns_record_t *dnsrec, ares_array_t **requeue)
1414{1460{
1415 /* If we were probing for the server to come back online, lets mark it as1461 /* If we were probing for the server to come back online, lets mark it as
1416 * no longer being probed */1462 * no longer being probed */
@@ -1420,6 +1466,12 @@ static void end_query(ares_channel_t *channel, ares_server_t *server,
1420 1466 
1421 ares_metrics_record(query, server, status, dnsrec);1467 ares_metrics_record(query, server, status, dnsrec);
1422 1468 
1469+ /* Delay calling the query callback */
1470+ if (requeue != NULL) {
1471+ ares_append_endqueue(requeue, query, status, dnsrec);
1472+ return;
1473+ }
1474+ 
1423 /* Invoke the callback. */1475 /* Invoke the callback. */
1424 query->callback(query->arg, status, query->timeouts, dnsrec);1476 query->callback(query->arg, status, query->timeouts, dnsrec);
1425 ares_free_query(query);1477 ares_free_query(query);
@@ -421,10 +421,20 @@ done:
421 return status;421 return status;
422}422}
423 423 
424-ares_status_t ares_qcache_insert(ares_channel_t *channel,424+ ares_status_t ares_qcache_insert(ares_channel_t *channel,
425- const ares_timeval_t *now,425+ const ares_timeval_t *now,
426- const ares_query_t *query,426+ const ares_query_t *query,
427- ares_dns_record_t *dnsrec)427+ const ares_dns_record_t *dnsrec)
428{428{
429- return ares_qcache_insert_int(channel->qcache, dnsrec, query->query, now);429+ ares_dns_record_t *dupdns = ares_dns_record_duplicate(dnsrec);
430+ ares_status_t status;
431+
432+ if (dupdns == NULL) {
433+ return ARES_ENOMEM;
434+ }
435+ status = ares_qcache_insert_int(channel->qcache, dupdns, query->query, now);
436+ if (status != ARES_SUCCESS) {
437+ ares_dns_record_destroy(dupdns);
438+ }
439+ return status;
430}440}
@@ -805,7 +805,39 @@ TEST_P(MockUDPChannelTestAI, TriggerResendThenConnFailEDNS) {
805 EXPECT_THAT(result.ai_, IncludesV6Address("2121:0000:0000:0000:0000:0000:0000:0303"));805 EXPECT_THAT(result.ai_, IncludesV6Address("2121:0000:0000:0000:0000:0000:0000:0303"));
806}806}
807 807 
808- 808+TEST_P(MockUDPChannelTestAI, ConnectionRefusedOnSearchDomainRetry) {
809+ DNSPacket badrsp4;
810+ badrsp4.set_response().set_aa()
811+ .add_question(new DNSQuestion("www.google.com", T_A))
812+ .set_rcode(NXDOMAIN);
813+
814+ EXPECT_CALL(server_, OnRequest("www.google.com", T_A))
815+ .WillOnce(SetReplyAndFailSend(&server_, &badrsp4));
816+
817+ DNSPacket goodrsp4;
818+ goodrsp4.set_response().set_aa()
819+ .add_question(new DNSQuestion("www.google.com.first.com", T_A))
820+ .add_answer(new DNSARR("www.google.com.first.com", 0x0100, {0x01, 0x02, 0x03, 0x04}));
821+
822+ EXPECT_CALL(server_, OnRequest("www.google.com.first.com", T_A))
823+ .WillOnce(SetReply(&server_, &goodrsp4));
824+
825+ ares_socket_functions sock_funcs;
826+ memset(&sock_funcs, 0, sizeof(sock_funcs));
827+
828+ sock_funcs.asendv = ares_sendv_fail;
829+
830+ ares_set_socket_functions(channel_, &sock_funcs, NULL);
831+
832+ AddrInfoResult result;
833+ struct ares_addrinfo_hints hints = {0, 0, 0, 0};
834+ hints.ai_family = AF_INET;
835+ hints.ai_flags = ARES_AI_NOSORT;
836+ ares_getaddrinfo(channel_, "www.google.com", NULL, &hints,
837+ AddrInfoCallback, &result);
838+
839+ Process();
840+}
809 841 
810class MockEDNSChannelTestAI : public MockFlagsChannelOptsTestAI {842class MockEDNSChannelTestAI : public MockFlagsChannelOptsTestAI {
811 public:843 public: