bind 9.16 回根查询流程(非本地权威查询,无本地cache缓存,须回根的完整查询,递归通信部分)

接上篇文章,回根查询流程业务部分,本篇主要分析回根通信部分

1。 本部分激发入口是fctx_start(isc_task_t *task, isc_event_t *event)

	if (!done) {
		isc_result_t result;

		INSIST(!dodestroy);

		/*
		 * All is well.  Start working on the fetch.
		 */
		result = fctx_starttimer(fctx);
		if (result == ISC_R_SUCCESS && fctx->timer_try_stale != NULL) {
			result = fctx_starttimer_trystale(fctx);
		}
		if (result != ISC_R_SUCCESS) {
			fctx_done(fctx, result, __LINE__);
		} else {
			fctx_try(fctx, false, false);
		}
	} else if (dodestroy) {
		fctx_destroy(fctx);
		if (bucket_empty) {
			empty_bucket(res);
		}
	}

此部分代码,就是对通信查询部分的开始,首先将自己这个查询上下文置一下陈旧定时器,若超时到期望,则停掉本次查询

若定时器设置成功,则fctx_try(fctx, false, false)

2。 函数实际,不需要重试,不是坏的缓存

static void
fctx_try(fetchctx_t *fctx, bool retrying, bool badcache) {

在如下代码是查询可用的ns名字,代码如下,此代码封装比较好,多多种处理,包括forward转发,cache缓存,等等等等,查询机制,重点在于fctx_nextaddress内

	addrinfo = fctx_nextaddress(fctx);

	/* Try to find an address that isn't over quota */
	while (addrinfo != NULL && dns_adbentry_overquota(addrinfo->entry)) {
		addrinfo = fctx_nextaddress(fctx);
	}

若查询到合适的addrinfo

最终到向ns发送查询数据:代码:

	result = fctx_query(fctx, addrinfo, fctx->options);
	if (result != ISC_R_SUCCESS) {
		fctx_done(fctx, result, __LINE__);
		LOCK(&res->buckets[bucketnum].lock);
		bucket_empty = fctx_decreference(fctx);
		UNLOCK(&res->buckets[bucketnum].lock);
		if (bucket_empty) {
			empty_bucket(res);
		}
	} else if (retrying) {
		inc_stats(res, dns_resstatscounter_retry);
	}

3。 fctx_query

在代码位置:

	fctx_setretryinterval(fctx, srtt);
	result = fctx_startidletimer(fctx, &fctx->interval);
	if (result != ISC_R_SUCCESS) {
		return (result);
	}

此部分设置定时器,防止网络不通等异常机制

数据的真正发送位置在本函数的代码

		result = resquery_send(query);
		if (result != ISC_R_SUCCESS) {
			goto cleanup_dispatch;
		}

此地方使用了sendmsg方式

4。 函数static isc_result_t resquery_send(resquery_t *query) {

是实际的发送函数

具体发送位置

	result = isc_socket_sendto2(sock, &r, task, address, NULL,
				    &query->sendevent, 0);

5。 函数isc_socket_sendto2

isc_result_t
isc_socket_sendto2(isc_socket_t *sock0, isc_region_t *region, isc_task_t *task,
		   const isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
		   isc_socketevent_t *event, unsigned int flags) {

本函数调用如下函数:

6。

static isc_result_t
socket_send(isc__socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
	    const isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
	    unsigned int flags) {

本函数做一些一场判断,在继续调用函数

	if (sock->type == isc_sockettype_udp) {
		io_state = doio_send(sock, dev);
	} else {
		LOCK(&sock->lock);
		have_lock = true;

		if (ISC_LIST_EMPTY(sock->send_list)) {
			io_state = doio_send(sock, dev);
		} else {
			io_state = DOIO_SOFT;
		}
	}

 

7。 doio_send就是实际 的发送函数

static int
doio_send(isc__socket_t *sock, isc_socketevent_t *dev) {
	int cc;
	struct iovec iov[MAXSCATTERGATHER_SEND];
	size_t write_count;
	struct msghdr msghdr;
	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
	int attempts = 0;
	int send_errno;
	char strbuf[ISC_STRERRORSIZE];
	char cmsgbuf[SENDCMSGBUFLEN] = { 0 };

	build_msghdr_send(sock, cmsgbuf, dev, &msghdr, iov, &write_count);
resend:
	if (sock->type == isc_sockettype_udp && sock->manager->maxudp != 0 &&
	    write_count > sock->manager->maxudp)
	{
		cc = write_count;
	} else {
		cc = sendmsg(sock->fd, &msghdr, 0);
	}
	send_errno = errno;

到现在就是发送数据的整个流程

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值