📄 ares_process.c
字号:
* with SERVFAIL, NOTIMP, or REFUSED response codes. */ if (!(channel->flags & ARES_FLAG_NOCHECKRESP)) { if (rcode == SERVFAIL || rcode == NOTIMP || rcode == REFUSED) { query->skip_server[whichserver] = 1; if (query->server == whichserver) next_server(channel, query, now); return; } if (!same_questions(query->qbuf, query->qlen, abuf, alen)) { if (query->server == whichserver) next_server(channel, query, now); return; } } end_query(channel, query, ARES_SUCCESS, abuf, alen);}static void handle_error(ares_channel channel, int whichserver, time_t now){ struct query *query; /* Reset communications with this server. */ ares__close_sockets(&channel->servers[whichserver]); /* Tell all queries talking to this server to move on and not try * this server again. */ for (query = channel->queries; query; query = query->next) { if (query->server == whichserver) { query->skip_server[whichserver] = 1; next_server(channel, query, now); } }}static void next_server(ares_channel channel, struct query *query, time_t now){ /* Advance to the next server or try. */ query->server++; for (; query->try < channel->tries; query->try++) { for (; query->server < channel->nservers; query->server++) { if (!query->skip_server[query->server]) { ares__send_query(channel, query, now); return; } } query->server = 0; /* Only one try if we're using TCP. */ if (query->using_tcp) break; } end_query(channel, query, query->error_status, NULL, 0);}void ares__send_query(ares_channel channel, struct query *query, time_t now){ struct send_request *sendreq; struct server_state *server; server = &channel->servers[query->server]; if (query->using_tcp) { /* Make sure the TCP socket for this server is set up and queue * a send request. */ if (server->tcp_socket == -1) { if (open_tcp_socket(channel, server) == -1) { query->skip_server[query->server] = 1; next_server(channel, query, now); return; } } sendreq = malloc(sizeof(struct send_request)); if (!sendreq) end_query(channel, query, ARES_ENOMEM, NULL, 0); sendreq->data = query->tcpbuf; sendreq->len = query->tcplen; sendreq->next = NULL; if (server->qtail) server->qtail->next = sendreq; else server->qhead = sendreq; server->qtail = sendreq; query->timeout = 0; } else { if (server->udp_socket == -1) { if (open_udp_socket(channel, server) == -1) { query->skip_server[query->server] = 1; next_server(channel, query, now); return; } } if (send(server->udp_socket, (void *) query->qbuf, query->qlen, 0) == -1) { query->skip_server[query->server] = 1; next_server(channel, query, now); return; } query->timeout = now + ((query->try == 0) ? channel->timeout : channel->timeout << query->try / channel->nservers); }}static int open_tcp_socket(ares_channel channel, struct server_state *server){ int s; struct sockaddr_in sin; /* Acquire a socket. */ s = socket(AF_INET, SOCK_STREAM, 0); if (s == -1) return -1; /* Set the socket non-blocking. */#ifdef __LWIP_SOCKETS_H__ { u32_t on = 1; if (lwip_ioctl(s, FIONBIO, &on)) { close(s); return -1; } }#else { int flags; if (fcntl(s, F_GETFL, &flags) == -1) { close(s); return -1; } flags &= O_NONBLOCK; if (fcntl(s, F_SETFL, flags) == -1) { close(s); return -1; } }#endif /* Connect to the server. */ memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr = server->addr; sin.sin_port = channel->tcp_port; if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == -1 && errno != EINPROGRESS) { close(s); return -1; } server->tcp_socket = s; return 0;}static int open_udp_socket(ares_channel channel, struct server_state *server){ int s; struct sockaddr_in sin; /* Acquire a socket. */ s = socket(AF_INET, SOCK_DGRAM, 0); if (s == -1) return -1; /* Connect to the server. */ memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr = server->addr; sin.sin_port = channel->udp_port; if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) { close(s); return -1; } server->udp_socket = s; return 0;}static int same_questions(const unsigned char *qbuf, int qlen, const unsigned char *abuf, int alen){ struct { const unsigned char *p; int qdcount; char *name; int namelen; int type; int dnsclass; } q, a; int i, j; if (qlen < HFIXEDSZ || alen < HFIXEDSZ) return 0; /* Extract qdcount from the request and reply buffers and compare them. */ q.qdcount = DNS_HEADER_QDCOUNT(qbuf); a.qdcount = DNS_HEADER_QDCOUNT(abuf); if (q.qdcount != a.qdcount) return 0; /* For each question in qbuf, find it in abuf. */ q.p = qbuf + HFIXEDSZ; for (i = 0; i < q.qdcount; i++) { /* Decode the question in the query. */ if (ares_expand_name(q.p, qbuf, qlen, &q.name, &q.namelen) != ARES_SUCCESS) return 0; q.p += q.namelen; if (q.p + QFIXEDSZ > qbuf + qlen) { free(q.name); return 0; } q.type = DNS_QUESTION_TYPE(q.p); q.dnsclass = DNS_QUESTION_CLASS(q.p); q.p += QFIXEDSZ; /* Search for this question in the answer. */ a.p = abuf + HFIXEDSZ; for (j = 0; j < a.qdcount; j++) { /* Decode the question in the answer. */ if (ares_expand_name(a.p, abuf, alen, &a.name, &a.namelen) != ARES_SUCCESS) { free(q.name); return 0; } a.p += a.namelen; if (a.p + QFIXEDSZ > abuf + alen) { free(q.name); free(a.name); return 0; } a.type = DNS_QUESTION_TYPE(a.p); a.dnsclass = DNS_QUESTION_CLASS(a.p); a.p += QFIXEDSZ; /* Compare the decoded questions. */ if (strcasecmp(q.name, a.name) == 0 && q.type == a.type && q.dnsclass == a.dnsclass) { free(a.name); break; } free(a.name); } free(q.name); if (j == a.qdcount) return 0; } return 1;}static void end_query(ares_channel channel, struct query *query, int status, unsigned char *abuf, int alen){ struct query **q; int i; query->callback(query->arg, status, abuf, alen); for (q = &channel->queries; *q; q = &(*q)->next) { if (*q == query) break; } *q = query->next; free(query->tcpbuf); free(query->skip_server); free(query); /* Simple cleanup policy: if no queries are remaining, close all * network sockets unless STAYOPEN is set. */ if (!channel->queries && !(channel->flags & ARES_FLAG_STAYOPEN)) { for (i = 0; i < channel->nservers; i++) ares__close_sockets(&channel->servers[i]); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -