📄 ares_search.c
字号:
/* Copyright 1998 by the Massachusetts Institute of Technology. * * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without * fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright * notice and this permission notice appear in supporting * documentation, and that the name of M.I.T. not be used in * advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" * without express or implied warranty. * * CHANGELOG: this file has been modified by Sergio Perez Alca駃z <serpeal@upvnet.upv.es> * Departamento de Inform醫ica de Sistemas y Computadores * Universidad Polit閏nica de Valencia * Valencia (Spain) * Date: April 2003 * */#include "ares_private.h"struct search_query { /* Arguments passed to ares_search */ ares_channel channel; char *name; /* copied into an allocated buffer */ int dnsclass; int type; ares_callback callback; void *arg; int status_as_is; /* error status from trying as-is */ int next_domain; /* next search domain to try */ int trying_as_is; /* current query is for name as-is */};static void search_callback(void *arg, int status, unsigned char *abuf, int alen);static void end_squery(struct search_query *squery, int status, unsigned char *abuf, int alen);static int cat_domain(const char *name, const char *domain, char **s);static int single_domain(ares_channel channel, const char *name, char **s);void ares_search(ares_channel channel, const char *name, int dnsclass, int type, ares_callback callback, void *arg){ struct search_query *squery; char *s; const char *p; int status, ndots; /* If name only yields one domain to search, then we don't have * to keep extra state, so just do an ares_query(). */ status = single_domain(channel, name, &s); if (status != ARES_SUCCESS) { callback(arg, status, NULL, 0); return; } if (s) { ares_query(channel, s, dnsclass, type, callback, arg); free(s); return; } /* Allocate a search_query structure to hold the state necessary for * doing multiple lookups. */ squery = malloc(sizeof(struct search_query)); if (!squery) { callback(arg, ARES_ENOMEM, NULL, 0); return; } squery->channel = channel; squery->name = strdup(name); if(!squery->name) { free(squery); callback(arg, ARES_ENOMEM, NULL, 0); return; } squery->dnsclass = dnsclass; squery->type = type; squery->status_as_is = -1; squery->callback = callback; squery->arg = arg; /* Count the number of dots in name. */ ndots = 0; for (p = name; *p; p++) { if (*p == '.') ndots++; } /* If ndots is at least the channel ndots threshold (usually 1), * then we try the name as-is first. Otherwise, we try the name * as-is last. */ if (ndots >= channel->ndots) { /* Try the name as-is first. */ squery->next_domain = 0; squery->trying_as_is = 1; ares_query(channel, name, dnsclass, type, search_callback, squery); } else { /* Try the name as-is last; start with the first search domain. */ squery->next_domain = 1; squery->trying_as_is = 0; status = cat_domain(name, channel->domains[0], &s); if (status == ARES_SUCCESS) { ares_query(channel, s, dnsclass, type, search_callback, squery); free(s); } else callback(arg, status, NULL, 0); }}static void search_callback(void *arg, int status, unsigned char *abuf, int alen){ struct search_query *squery = (struct search_query *) arg; ares_channel channel = squery->channel; char *s; /* Stop searching unless we got a non-fatal error. */ if (status != ARES_ENODATA && status != ARES_ESERVFAIL && status != ARES_ENOTFOUND) end_squery(squery, status, abuf, alen); else { /* Save the status if we were trying as-is. */ if (squery->trying_as_is) squery->status_as_is = status; if (squery->next_domain < channel->ndomains) { /* Try the next domain. */ status = cat_domain(squery->name, channel->domains[squery->next_domain], &s); if (status != ARES_SUCCESS) end_squery(squery, status, NULL, 0); else { squery->trying_as_is = 0; squery->next_domain++; ares_query(channel, s, squery->dnsclass, squery->type, search_callback, squery); free(s); } } else if (squery->status_as_is == -1) { /* Try the name as-is at the end. */ squery->trying_as_is = 1; ares_query(channel, squery->name, squery->dnsclass, squery->type, search_callback, squery); } else end_squery(squery, squery->status_as_is, NULL, 0); }}static void end_squery(struct search_query *squery, int status, unsigned char *abuf, int alen){ squery->callback(squery->arg, status, abuf, alen); free(squery->name); free(squery);}/* Concatenate two domains. */static int cat_domain(const char *name, const char *domain, char **s){ int nlen = strlen(name), dlen = strlen(domain); *s = malloc(nlen + 1 + dlen + 1); if (!*s) return ARES_ENOMEM; memcpy(*s, name, nlen); (*s)[nlen] = '.'; memcpy(*s + nlen + 1, domain, dlen); (*s)[nlen + 1 + dlen] = 0; return ARES_SUCCESS;}/* Determine if this name only yields one query. If it does, set *s to * the string we should query, in an allocated buffer. If not, set *s * to NULL. */static int single_domain(ares_channel channel, const char *name, char **s){ int len = strlen(name); /* If the name contains a trailing dot, then the single query is the name * sans the trailing dot. */ if (name[len - 1] == '.') { *s = strdup(name); return (*s) ? ARES_SUCCESS : ARES_ENOMEM; } if (channel->flags & ARES_FLAG_NOSEARCH || channel->ndomains == 0) { /* No domain search to do; just try the name as-is. */ *s = strdup(name); return (*s) ? ARES_SUCCESS : ARES_ENOMEM; } *s = NULL; return ARES_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -