⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sres.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 5 页
字号:
    return su_seterrno(EFAULT);  for (n = 0, i = 0; answers[i]; i++) {    if (answers[i]->sr_record->r_status ||	answers[i]->sr_record->r_class != sres_class_in ||	(type != 0 && answers[i]->sr_record->r_type != type)) {      sres_free_answer(res, answers[i]);      continue;    }    answers[n++] = answers[i];  }  answers[n] = NULL;  sres_sort_answers(res, answers);  return n;}/** Free and zero one record. */void sres_free_answer(sres_resolver_t *res, sres_record_t *answer){  if (res && answer)    sres_cache_free_one(res->res_cache, answer);}/** Free and zero an array of records. *  * The array of records can be returned by sres_cached_answers() or  * given by callback function. */void sres_free_answers(sres_resolver_t *res,		  sres_record_t **answers){  if (res && answers)    sres_cache_free_answers(res->res_cache, answers);}/** Convert type to its name. */char const *sres_record_type(int type, char buffer[8]){  switch (type) {  case sres_type_a: return "A";  case sres_type_ns: return "NS";  case sres_type_mf: return "MF";  case sres_type_cname: return "CNAME";  case sres_type_soa: return "SOA";  case sres_type_mb: return "MB";  case sres_type_mg: return "MG";  case sres_type_mr: return "MR";  case sres_type_null: return "NULL";  case sres_type_wks: return "WKS";  case sres_type_ptr: return "PTR";  case sres_type_hinfo: return "HINFO";  case sres_type_minfo: return "MINFO";  case sres_type_mx: return "MX";  case sres_type_txt: return "TXT";  case sres_type_rp: return "RP";  case sres_type_afsdb: return "AFSDB";  case sres_type_x25: return "X25";  case sres_type_isdn: return "ISDN";  case sres_type_rt: return "RT";  case sres_type_nsap: return "NSAP";  case sres_type_nsap_ptr: return "NSAP_PTR";  case sres_type_sig: return "SIG";  case sres_type_key: return "KEY";  case sres_type_px: return "PX";  case sres_type_gpos: return "GPOS";  case sres_type_aaaa: return "AAAA";  case sres_type_loc: return "LOC";  case sres_type_nxt: return "NXT";  case sres_type_eid: return "EID";  case sres_type_nimloc: return "NIMLOC";  case sres_type_srv: return "SRV";  case sres_type_atma: return "ATMA";  case sres_type_naptr: return "NAPTR";  case sres_type_kx: return "KX";  case sres_type_cert: return "CERT";  case sres_type_a6: return "A6";  case sres_type_dname: return "DNAME";  case sres_type_sink: return "SINK";  case sres_type_opt: return "OPT";  case sres_qtype_tsig: return "TSIG";  case sres_qtype_ixfr: return "IXFR";  case sres_qtype_axfr: return "AXFR";  case sres_qtype_mailb: return "MAILB";  case sres_qtype_maila: return "MAILA";  case sres_qtype_any: return "ANY";      default:    sprintf(buffer, "%u?", type & 65535);    return buffer;  }}/** Convert class to its name. */char const *sres_record_class(int rclass, char buffer[8]){  switch (rclass) {  case 1: return "IN";  case 2: return "2?";  case 3: return "CHAOS";  case 4: return "HS";  case 254: return "NONE";  case 255: return "ANY";  default:    sprintf(buffer, "%u?", rclass & 65535);    return buffer;  }}/** Compare two records. */int sres_record_compare(sres_record_t const *aa, sres_record_t const *bb){  int D;  sres_common_t const *a = aa->sr_record, *b = bb->sr_record;  D = a->r_status - b->r_status; if (D) return D;  D = a->r_class - b->r_class; if (D) return D;  D = a->r_type - b->r_type; if (D) return D;  if (a->r_status)    return 0;    switch (a->r_type) {  case sres_type_soa:     {      sres_soa_record_t const *A = aa->sr_soa, *B = bb->sr_soa;      D = A->soa_serial - B->soa_serial; if (D) return D;      D = strcasecmp(A->soa_mname, B->soa_mname); if (D) return D;      D = strcasecmp(A->soa_rname, B->soa_rname); if (D) return D;      D = A->soa_refresh - B->soa_refresh; if (D) return D;      D = A->soa_retry - B->soa_retry; if (D) return D;      D = A->soa_expire - B->soa_expire; if (D) return D;      D = A->soa_minimum - B->soa_minimum; if (D) return D;      return 0;    }  case sres_type_a:    {      sres_a_record_t const *A = aa->sr_a, *B = bb->sr_a;      return memcmp(&A->a_addr, &B->a_addr, sizeof A->a_addr);    }  case sres_type_a6:    {      sres_a6_record_t const *A = aa->sr_a6, *B = bb->sr_a6;      D = A->a6_prelen - B->a6_prelen; if (D) return D;      D = !A->a6_prename - !B->a6_prename;       if (D == 0 && A->a6_prename && B->a6_prename)	D = strcasecmp(A->a6_prename, B->a6_prename); if (D) return D;      return memcmp(&A->a6_suffix, &B->a6_suffix, sizeof A->a6_suffix);    }  case sres_type_aaaa:    {      sres_aaaa_record_t const *A = aa->sr_aaaa, *B = bb->sr_aaaa;      return memcmp(&A->aaaa_addr, &B->aaaa_addr, sizeof A->aaaa_addr);          }  case sres_type_cname:    {      sres_cname_record_t const *A = aa->sr_cname, *B = bb->sr_cname;      return strcmp(A->cn_cname, B->cn_cname);    }  case sres_type_ptr:    {      sres_ptr_record_t const *A = aa->sr_ptr, *B = bb->sr_ptr;      return strcmp(A->ptr_domain, B->ptr_domain);    }  case sres_type_srv:    {      sres_srv_record_t const *A = aa->sr_srv, *B = bb->sr_srv;      D = A->srv_priority - B->srv_priority; if (D) return D;      /* Record with larger weight first */      D = B->srv_weight - A->srv_weight; if (D) return D;      D = strcmp(A->srv_target, B->srv_target); if (D) return D;      return A->srv_port - B->srv_port;    }  case sres_type_naptr:    {      sres_naptr_record_t const *A = aa->sr_naptr, *B = bb->sr_naptr;      D = A->na_order - B->na_order; if (D) return D;      D = A->na_prefer - B->na_prefer; if (D) return D;      D = strcmp(A->na_flags, B->na_flags); if (D) return D;      D = strcmp(A->na_services, B->na_services); if (D) return D;      D = strcmp(A->na_regexp, B->na_regexp); if (D) return D;      return strcmp(A->na_replace, B->na_replace);     }  default:    return 0;  }}/* ---------------------------------------------------------------------- *//* Private functions *//** Destruct */static void sres_resolver_destructor(void *arg){  sres_resolver_t *res = arg;  assert(res);  sres_cache_unref(res->res_cache);   res->res_cache = NULL;  sres_servers_close(res, res->res_servers);  if (res->res_config)    su_home_unref((su_home_t *)res->res_config->c_home);  if (res->res_updcb)    res->res_updcb(res->res_async, INVALID_SOCKET, INVALID_SOCKET);}/* * 3571 is a prime =>  * we hash successive id values to different parts of hash tables */#define Q_PRIME 3571#define SRES_QUERY_HASH(q) ((q)->q_hash)HTABLE_BODIES_WITH(sres_qtable, qt, sres_query_t, SRES_QUERY_HASH,		   unsigned, size_t);/** Allocate a query structure */staticsres_query_t *sres_query_alloc(sres_resolver_t *res,		 sres_answer_f *callback,		 sres_context_t *context,		 uint16_t type,		 char const *domain){  sres_query_t *query;  size_t dlen = strlen(domain);  if (sres_qtable_is_full(res->res_queries))    if (sres_qtable_resize(res->res_home, res->res_queries, 0) < 0)      return NULL;  query = su_alloc(res->res_home, sizeof(*query) + dlen + 1);  if (query) {    memset(query, 0, sizeof *query);    query->q_res = res;    query->q_callback = callback;    query->q_context = context;    query->q_type = type;    query->q_class = sres_class_in;    query->q_timestamp = res->res_now;    query->q_name = strcpy((char *)(query + 1), domain);    query->q_id = sres_new_id(res); assert(query->q_id);    query->q_i_server = res->res_i_server;    query->q_n_servers = res->res_n_servers;    query->q_hash = query->q_id * Q_PRIME /* + query->q_i_server */;        sres_qtable_append(res->res_queries, query);    if (res->res_schedulecb && res->res_queries->qt_used == 1)      res->res_schedulecb(res->res_async, 2 * SRES_RETRANSMIT_INTERVAL);   }  return query;}su_inlinevoid sres_remove_query(sres_resolver_t *res, sres_query_t *q, int all){  int i;  if (q->q_hash) {    sres_qtable_remove(res->res_queries, q), q->q_hash = 0;    if (all)      for (i = 0; i <= SRES_MAX_SEARCH; i++) {	if (q->q_subqueries[i] && q->q_subqueries[i]->q_hash) {	  sres_qtable_remove(res->res_queries, q->q_subqueries[i]);	  q->q_subqueries[i]->q_hash = 0;	}      }  }}/** Remove a query from hash table and free it. */staticvoid sres_free_query(sres_resolver_t *res, sres_query_t *q){  int i;  if (q == NULL)    return;  if (q->q_hash)    sres_qtable_remove(res->res_queries, q), q->q_hash = 0;  for (i = 0; i <= SRES_MAX_SEARCH; i++) {    sres_query_t *sq;    sq = q->q_subqueries[i];    q->q_subqueries[i] = NULL;    if (sq)      sres_free_query(res, sq);    if (q->q_subanswers[i])      sres_cache_free_answers(res->res_cache, q->q_subanswers[i]);    q->q_subanswers[i] = NULL;  }   su_free(res->res_home, q);}staticsres_record_t **sres_combine_results(sres_resolver_t *res,		     sres_record_t **search_results[SRES_MAX_SEARCH + 1]){  sres_record_t **combined_result;  int i, j, found;  /* Combine the results into a single list. */  for (i = 0, found = 0; i <= SRES_MAX_SEARCH; i++)    if (search_results[i])      for (j = 0; search_results[i][j]; j++)	found++;  combined_result = su_alloc((su_home_t *)res->res_cache, 			     (found + 1) * (sizeof combined_result[0]));  if (combined_result) {    for (i = 0, found = 0; i <= SRES_MAX_SEARCH; i++)      if (search_results[i])	for (j = 0; search_results[i][j]; j++) {	  combined_result[found++] = search_results[i][j];	  search_results[i][j] = NULL;	}    combined_result[found] = NULL;    sres_sort_answers(res, combined_result);  }  for (i = 0; i <= SRES_MAX_SEARCH; i++)    if (search_results[i])      sres_free_answers(res, search_results[i]), search_results[i] = NULL;  return combined_result;}staticintsres_sockaddr2string(sres_resolver_t *res,		     char name[],		     size_t namelen,		     struct sockaddr const *addr){  name[0] = '\0';  if (addr->sa_family == AF_INET) {    struct sockaddr_in const *sin = (struct sockaddr_in *)addr;    uint8_t const *in_addr = (uint8_t*)&sin->sin_addr;    return snprintf(name, namelen, "%u.%u.%u.%u.in-addr.arpa.",		    in_addr[3], in_addr[2], in_addr[1], in_addr[0]);  }#if HAVE_SIN6  else if (addr->sa_family == AF_INET6) {    struct sockaddr_in6 const *sin6 = (struct sockaddr_in6 *)addr;    size_t addrsize = sizeof(sin6->sin6_addr.s6_addr);    char *postfix;    size_t required;    size_t i;    if (res->res_config->c_opt.ip6int)      postfix = "ip6.int.";    else      postfix = "ip6.arpa.";    required = addrsize * 4 + strlen(postfix);    if (namelen <= required)      return (int)required;    for (i = 0; i < addrsize; i++) {      uint8_t byte = sin6->sin6_addr.s6_addr[addrsize - i - 1];      uint8_t hex;      hex = byte & 0xf;      name[4 * i] = hex > 9 ? hex + 'a' - 10 : hex + '0';      name[4 * i + 1] = '.';      hex = (byte >> 4) & 0xf;      name[4 * i + 2] = hex > 9 ? hex + 'a' - 10 : hex + '0';      name[4 * i + 3] = '.';    }        strcpy(name + 4 * i, postfix);    return (int)required;  }#endif /* HAVE_SIN6 */  else {    su_seterrno(EAFNOSUPPORT);    SU_DEBUG_3(("%s: %s\n", "sres_sockaddr2string",                 su_strerror(EAFNOSUPPORT)));    return 0;  }}/** Make a domain name a top level domain name. * * The function sres_toplevel() returns a copies string @a domain and  * terminates it with a dot if it is not already terminated.  */staticchar const *sres_toplevel(char buf[], size_t blen, char const *domain){  size_t len;  int already;  if (!domain)    return su_seterrno(EFAULT), (void *)NULL;  len = strlen(domain);  if (len >= blen)    return su_seterrno(ENAMETOOLONG), (void *)NULL;  already = len > 0 && domain[len - 1] == '.';  if (already)    return domain;  if (len + 1 >= blen)    return su_seterrno(ENAMETOOLONG), (void *)NULL;  strcpy(buf, domain);  buf[len] = '.'; buf[len + 1] = '\0';  return buf;}/* ---------------------------------------------------------------------- */static int sres_update_config(sres_resolver_t *res, int always, time_t now);static int sres_parse_config(sres_config_t *, FILE *);static int sres_parse_options(sres_config_t *c, char const *value);static int sres_parse_nameserver(sres_config_t *c, char const *server);static time_t sres_config_timestamp(sres_config_t const *c);/** Update configuration * * @retval 0 when successful * @retval -1 upon an error */int sres_resolver_update(sres_resolver_t *res, int always){  sres_server_t **servers, **old_servers;  int updated;  updated = sres_update_config(res, always, time(&res->res_now));  if (updated < 0)    return -1;  if (!res->res_servers || always || updated) {    servers = sres_servers_new(res, res->res_config);    old_servers = res->res_servers;    res->res_i_server = 0;    res->res_n_servers = sres_servers_count(servers);    res->res_servers = servers;    sres_servers_close(res, old_servers);    su_free(res->res_home, old_servers);    if (!servers)      return -1;  }  return 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -