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

📄 srv_resolver.c

📁 一个开源的sip源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	      response->hdr.anscount,
	      (query_job->srv_cnt ? ':' : ' ')));

    for (i=0; i<query_job->srv_cnt; ++i) {
	const char *addr;

	if (query_job->srv[i].addr_cnt != 0)
	    addr = pj_inet_ntoa(query_job->srv[i].addr[0]);
	else
	    addr = "-";

	PJ_LOG(5,(query_job->objname, 
		  " %d: SRV %d %d %d %.*s (%s)",
		  i, query_job->srv[i].priority, 
		  query_job->srv[i].weight, 
		  query_job->srv[i].port, 
		  (int)query_job->srv[i].target_name.slen, 
		  query_job->srv[i].target_name.ptr,
		  addr));
    }
}


/* Start DNS A record queries for all SRV records in the query_job structure */
static pj_status_t resolve_hostnames(pj_dns_srv_resolver_job *query_job)
{
    unsigned i;
    pj_status_t err=PJ_SUCCESS, status;

    query_job->dns_state = PJ_DNS_TYPE_A;
    for (i=0; i<query_job->srv_cnt; ++i) {
	PJ_LOG(5, (query_job->objname, 
		   "Starting async DNS A query_job for %.*s",
		   (int)query_job->srv[i].target_name.slen, 
		   query_job->srv[i].target_name.ptr));

	status = pj_dns_resolver_start_query(query_job->resolver,
					     &query_job->srv[i].target_name,
					     PJ_DNS_TYPE_A, 0,
					     &dns_callback,
					     query_job, NULL);
	if (status != PJ_SUCCESS) {
	    query_job->host_resolved++;
	    err = status;
	}
    }
    
    return (query_job->host_resolved == query_job->srv_cnt) ? err : PJ_SUCCESS;
}

/* 
 * This callback is called by PJLIB-UTIL DNS resolver when asynchronous
 * query_job has completed (successfully or with error).
 */
static void dns_callback(void *user_data,
			 pj_status_t status,
			 pj_dns_parsed_packet *pkt)
{
    pj_dns_srv_resolver_job *query_job = (pj_dns_srv_resolver_job*) user_data;
    unsigned i;

    /* Proceed to next stage */

    if (query_job->dns_state == PJ_DNS_TYPE_SRV) {

	/* We are getting SRV response */

	if (status == PJ_SUCCESS && pkt->hdr.anscount != 0) {
	    /* Got SRV response, build server entry. If A records are available
	     * in additional records section of the DNS response, save them too.
	     */
	    build_server_entries(query_job, pkt);

	} else if (status != PJ_SUCCESS) {
	    char errmsg[PJ_ERR_MSG_SIZE];

	    /* Update query_job last error */
	    query_job->last_error = status;

	    pj_strerror(status, errmsg, sizeof(errmsg));
	    PJ_LOG(4,(query_job->objname, 
		      "DNS SRV resolution failed for %.*s: %s", 
		      (int)query_job->full_name.slen, 
		      query_job->full_name.ptr,
		      errmsg));

	    /* Trigger error when fallback is disabled */
	    if (query_job->fallback_a == PJ_FALSE) {
		goto on_error;
	    }
	}

	/* If we can't build SRV record, assume the original target is
	 * an A record and resolve with DNS A resolution.
	 */
	if (query_job->srv_cnt == 0) {
	    /* Looks like we aren't getting any SRV responses.
	     * Resolve the original target as A record by creating a 
	     * single "dummy" srv record and start the hostname resolution.
	     */
	    PJ_LOG(4, (query_job->objname, 
		       "DNS SRV resolution failed for %.*s, trying "
		       "resolving A record for %.*s",
		       (int)query_job->full_name.slen, 
		       query_job->full_name.ptr,
		       (int)query_job->domain_part.slen,
		       query_job->domain_part.ptr));

	    /* Create a "dummy" srv record using the original target */
	    i = query_job->srv_cnt++;
	    pj_bzero(&query_job->srv[i], sizeof(query_job->srv[i]));
	    query_job->srv[i].target_name = query_job->domain_part;
	    query_job->srv[i].priority = 0;
	    query_job->srv[i].weight = 0;
	    query_job->srv[i].port = query_job->def_port;
	} 
	

	/* Resolve server hostnames (DNS A record) for hosts which don't have
	 * A record yet.
	 */
	if (query_job->host_resolved != query_job->srv_cnt) {
	    status = resolve_hostnames(query_job);
	    if (status != PJ_SUCCESS)
		goto on_error;

	    /* Must return now. Callback may have been called and query_job
	     * may have been destroyed.
	     */
	    return;
	}

    } else if (query_job->dns_state == PJ_DNS_TYPE_A) {

	/* Check that we really have answer */
	if (status==PJ_SUCCESS && pkt->hdr.anscount != 0) {
	    int ans_idx = -1;

	    /* Find the first DNS A record in the answer while processing
	     * the CNAME info found in the response.
	     */
	    for (i=0; i < pkt->hdr.anscount; ++i) {

		pj_dns_parsed_rr *rr = &pkt->ans[i];

		if (rr->type == PJ_DNS_TYPE_A) {

		    if (ans_idx == -1)
			ans_idx = i;

		} else if (rr->type == PJ_DNS_TYPE_CNAME) {
		    /* Find which server entry to be updated with
		     * the CNAME information.
		     */
		    unsigned j;
		    pj_str_t cname = rr->rdata.cname.name;

		    for (j=0; j<query_job->srv_cnt; ++j) 
		    {
			struct srv_target *srv = &query_job->srv[j];
			if (pj_stricmp(&rr->name, &srv->target_name)==0)
			{
			    /* Update CNAME info for this server entry */
			    srv->cname.ptr = srv->cname_buf;
			    pj_strncpy(&srv->cname, &cname, 
				       sizeof(srv->cname_buf));
			    break;
			}
		    }
		}
	    }

	    if (ans_idx == -1) {
		/* There's no DNS A answer! */
		PJ_LOG(5,(query_job->objname, 
			  "No DNS A record in response!"));
		status = PJLIB_UTIL_EDNSNOANSWERREC;
		goto on_error;
	    }

	    /* Update IP address of the corresponding hostname or CNAME */
	    for (i=0; i<query_job->srv_cnt; ++i) {
		pj_dns_parsed_rr *rr = &pkt->ans[ans_idx];
		struct srv_target *srv = &query_job->srv[i];

		if (pj_stricmp(&rr->name, &srv->target_name)==0 ||
		    pj_stricmp(&rr->name, &srv->cname)==0) 
		{
		    break;
		}
	    }

	    if (i == query_job->srv_cnt) {
		PJ_LOG(4,(query_job->objname, 
			  "Received answer to DNS A request with no matching "
			  "SRV record! The unknown name is %.*s",
			  (int)pkt->ans[ans_idx].name.slen, 
			  pkt->ans[ans_idx].name.ptr));
	    } else {
		unsigned j;

		query_job->srv[i].addr[query_job->srv[i].addr_cnt++].s_addr =
		    pkt->ans[ans_idx].rdata.a.ip_addr.s_addr;

		PJ_LOG(5,(query_job->objname, 
			  "DNS A for %.*s: %s",
			  (int)query_job->srv[i].target_name.slen, 
			  query_job->srv[i].target_name.ptr,
			  pj_inet_ntoa(pkt->ans[ans_idx].rdata.a.ip_addr)));

		/* Check for multiple IP addresses */
		for (j=ans_idx+1; j<pkt->hdr.anscount && 
			    query_job->srv[i].addr_cnt < ADDR_MAX_COUNT; ++j)
		{
		    query_job->srv[i].addr[query_job->srv[i].addr_cnt++].s_addr = 
			pkt->ans[j].rdata.a.ip_addr.s_addr;

		    PJ_LOG(5,(query_job->objname, 
			      "Additional DNS A for %.*s: %s",
			      (int)query_job->srv[i].target_name.slen, 
			      query_job->srv[i].target_name.ptr,
			      pj_inet_ntoa(pkt->ans[j].rdata.a.ip_addr)));
		}
	    }

	} else if (status != PJ_SUCCESS) {
	    char errmsg[PJ_ERR_MSG_SIZE];

	    /* Update last error */
	    query_job->last_error = status;

	    /* Log error */
	    pj_strerror(status, errmsg, sizeof(errmsg));
	    PJ_LOG(4,(query_job->objname, "DNS A record resolution failed: %s", 
		      errmsg));
	}

	++query_job->host_resolved;

    } else {
	pj_assert(!"Unexpected state!");
	query_job->last_error = status = PJ_EINVALIDOP;
	goto on_error;
    }

    /* Check if all hosts have been resolved */
    if (query_job->host_resolved == query_job->srv_cnt) {
	/* Got all answers, build server addresses */
	pj_dns_srv_record svr_addr;

	svr_addr.count = 0;
	for (i=0; i<query_job->srv_cnt; ++i) {
	    unsigned j;

	    /* Do we have IP address for this server? */
	    /* This log is redundant really.
	    if (query_job->srv[i].addr_cnt == 0) {
		PJ_LOG(5,(query_job->objname, 
			  " SRV target %.*s:%d does not have IP address!",
			  (int)query_job->srv[i].target_name.slen,
			  query_job->srv[i].target_name.ptr,
			  query_job->srv[i].port));
		continue;
	    }
	    */

	    for (j=0; j<query_job->srv[i].addr_cnt; ++j) {
		unsigned idx = svr_addr.count;
		pj_sockaddr_in *addr;

		svr_addr.entry[idx].priority = query_job->srv[i].priority;
		svr_addr.entry[idx].weight = query_job->srv[i].weight;
		svr_addr.entry[idx].addr_len = sizeof(pj_sockaddr_in);
	     
		addr = (pj_sockaddr_in*)&svr_addr.entry[idx].addr;
		pj_bzero(addr, sizeof(pj_sockaddr_in));
		addr->sin_family = PJ_AF_INET;
		addr->sin_addr = query_job->srv[i].addr[j];
		addr->sin_port = pj_htons((pj_uint16_t)query_job->srv[i].port);

		++svr_addr.count;
	    }
	}

	PJ_LOG(5,(query_job->objname, 
		  "Server resolution complete, %d server entry(s) found",
		  svr_addr.count));


	if (svr_addr.count > 0)
	    status = PJ_SUCCESS;
	else {
	    status = query_job->last_error;
	    if (status == PJ_SUCCESS)
		status = PJLIB_UTIL_EDNSNOANSWERREC;
	}

	/* Call the callback */
	(*query_job->cb)(query_job->token, status, &svr_addr);
    }


    return;

on_error:
    /* Check for failure */
    if (status != PJ_SUCCESS) {
	char errmsg[PJ_ERR_MSG_SIZE];
	PJ_UNUSED_ARG(errmsg);
	PJ_LOG(4,(query_job->objname, 
		  "DNS %s record resolution error for '%.*s'."
		  " Err=%d (%s)",
		  pj_dns_get_type_name(query_job->dns_state),
		  (int)query_job->domain_part.slen,
		  query_job->domain_part.ptr,
		  status,
		  pj_strerror(status,errmsg,sizeof(errmsg)).ptr));
	(*query_job->cb)(query_job->token, status, NULL);
	return;
    }
}


⌨️ 快捷键说明

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