Newer
Older
Steinar H. Gunderson
committed
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
*/
for (i = 0; i < channel->nservers; i++)
{
struct server_state *server = &channel->servers[i];
struct send_request *sendreq;
for (sendreq = server->qhead; sendreq; sendreq = sendreq->next)
if (sendreq->owner_query == query)
{
sendreq->owner_query = NULL;
assert(sendreq->data_storage == NULL);
if (status == ARES_SUCCESS)
{
/* We got a reply for this query, but this queued
* sendreq points into this soon-to-be-gone query's
* tcpbuf. Probably this means we timed out and queued
* the query for retransmission, then received a
* response before actually retransmitting. This is
* perfectly fine, so we want to keep the connection
* running smoothly if we can. But in the worst case
* we may have sent only some prefix of the query,
* with some suffix of the query left to send. Also,
* the buffer may be queued on multiple queues. To
* prevent dangling pointers to the query's tcpbuf and
* handle these cases, we just give such sendreqs
* their own copy of the query packet.
*/
sendreq->data_storage = malloc(sendreq->len);
if (sendreq->data_storage != NULL)
{
memcpy(sendreq->data_storage, sendreq->data, sendreq->len);
sendreq->data = sendreq->data_storage;
}
}
if ((status != ARES_SUCCESS) || (sendreq->data_storage == NULL))
{
/* We encountered an error (probably a timeout,
* suggesting the DNS server we're talking to is
* probably unreachable, wedged, or severely
* overloaded) or we couldn't copy the request, so
* mark the connection as broken. When we get to
* process_broken_connections() we'll close the
* connection and try to re-send requests to another
* server.
*/
server->is_broken = 1;
/* Just to be paranoid, zero out this sendreq... */
sendreq->data = NULL;
sendreq->len = 0;
}
}
}
Steinar H. Gunderson
committed
query->callback(query->arg, status, query->timeouts, abuf, alen);
Steinar H. Gunderson
committed
ares__free_query(query);
/* Simple cleanup policy: if no queries are remaining, close all
* network sockets unless STAYOPEN is set.
*/
Steinar H. Gunderson
committed
if (!(channel->flags & ARES_FLAG_STAYOPEN) &&
ares__is_list_empty(&(channel->all_queries)))
{
for (i = 0; i < channel->nservers; i++)
Daniel Stenberg
committed
ares__close_sockets(channel, &channel->servers[i]);
Steinar H. Gunderson
committed
}
void ares__free_query(struct query *query)
{
/* Remove the query from all the lists in which it is linked */
ares__remove_from_list(&(query->queries_by_qid));
ares__remove_from_list(&(query->queries_by_timeout));
ares__remove_from_list(&(query->queries_to_server));
ares__remove_from_list(&(query->all_queries));
/* Zero out some important stuff, to help catch bugs */
query->callback = NULL;
query->arg = NULL;
/* Deallocate the memory associated with the query */
free(query->tcpbuf);
free(query->server_info);
free(query);