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

📄 dispatch.c

📁 bind 9.3结合mysql数据库
💻 C
📖 第 1 页 / 共 4 页
字号:
		if (disp->maxrequests < maxrequests)			disp->maxrequests = maxrequests;		if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) == 0 &&		    (attributes & DNS_DISPATCHATTR_NOLISTEN) != 0)		{			disp->attributes |= DNS_DISPATCHATTR_NOLISTEN;			if (disp->recv_pending != 0)				isc_socket_cancel(disp->socket, disp->task,						  ISC_SOCKCANCEL_RECV);		}		UNLOCK(&disp->lock);		UNLOCK(&mgr->lock);		*dispp = disp;		return (ISC_R_SUCCESS);	}	/*	 * Nope, create one.	 */	result = dispatch_createudp(mgr, sockmgr, taskmgr, localaddr,				    maxrequests, attributes, &disp);	if (result != ISC_R_SUCCESS) {		UNLOCK(&mgr->lock);		return (result);	}	UNLOCK(&mgr->lock);	*dispp = disp;	return (ISC_R_SUCCESS);}/* * mgr should be locked. */static isc_result_tdispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,		   isc_taskmgr_t *taskmgr,		   isc_sockaddr_t *localaddr,		   unsigned int maxrequests,		   unsigned int attributes,		   dns_dispatch_t **dispp){	isc_result_t result;	dns_dispatch_t *disp;	isc_socket_t *sock;	/*	 * dispatch_allocate() checks mgr for us.	 */	disp = NULL;	result = dispatch_allocate(mgr, maxrequests, &disp);	if (result != ISC_R_SUCCESS)		return (result);	/*	 * This assumes that the IP stack will *not* quickly reallocate	 * the same port.  If it does continually reallocate the same port	 * then we need a mechanism to hold all the blacklisted sockets	 * until we find a usable socket.	 */ getsocket:	result = create_socket(sockmgr, localaddr, &sock);	if (result != ISC_R_SUCCESS)		goto deallocate_dispatch;	if (isc_sockaddr_getport(localaddr) == 0 && blacklisted(mgr, sock)) {		isc_socket_detach(&sock);		goto getsocket;	}	disp->socktype = isc_sockettype_udp;	disp->socket = sock;	disp->local = *localaddr;	disp->task = NULL;	result = isc_task_create(taskmgr, 0, &disp->task);	if (result != ISC_R_SUCCESS)		goto kill_socket;	disp->ctlevent = isc_event_allocate(mgr->mctx, disp,					    DNS_EVENT_DISPATCHCONTROL,					    destroy_disp, disp,					    sizeof(isc_event_t));	if (disp->ctlevent == NULL)		goto kill_task;	isc_task_setname(disp->task, "udpdispatch", disp);	attributes &= ~DNS_DISPATCHATTR_TCP;	attributes |= DNS_DISPATCHATTR_UDP;	disp->attributes = attributes;	/*	 * Append it to the dispatcher list.	 */	ISC_LIST_APPEND(mgr->list, disp, link);	mgr_log(mgr, LVL(90), "created UDP dispatcher %p", disp);	dispatch_log(disp, LVL(90), "created task %p", disp->task);	dispatch_log(disp, LVL(90), "created socket %p", disp->socket);	*dispp = disp;	return (ISC_R_SUCCESS);	/*	 * Error returns.	 */ kill_task:	isc_task_detach(&disp->task); kill_socket:	isc_socket_detach(&disp->socket); deallocate_dispatch:	dispatch_free(&disp);	return (result);}voiddns_dispatch_attach(dns_dispatch_t *disp, dns_dispatch_t **dispp) {	REQUIRE(VALID_DISPATCH(disp));	REQUIRE(dispp != NULL && *dispp == NULL);	LOCK(&disp->lock);	disp->refcount++;	UNLOCK(&disp->lock);	*dispp = disp;}/* * It is important to lock the manager while we are deleting the dispatch, * since dns_dispatch_getudp will call dispatch_find, which returns to * the caller a dispatch but does not attach to it until later.  _getudp * locks the manager, however, so locking it here will keep us from attaching * to a dispatcher that is in the process of going away. */voiddns_dispatch_detach(dns_dispatch_t **dispp) {	dns_dispatch_t *disp;	isc_boolean_t killit;	REQUIRE(dispp != NULL && VALID_DISPATCH(*dispp));	disp = *dispp;	*dispp = NULL;	LOCK(&disp->lock);	INSIST(disp->refcount > 0);	disp->refcount--;	killit = ISC_FALSE;	if (disp->refcount == 0) {		if (disp->recv_pending > 0)			isc_socket_cancel(disp->socket, disp->task,					  ISC_SOCKCANCEL_RECV);		disp->shutting_down = 1;	}	dispatch_log(disp, LVL(90), "detach: refcount %d", disp->refcount);	killit = destroy_disp_ok(disp);	UNLOCK(&disp->lock);	if (killit)		isc_task_send(disp->task, &disp->ctlevent);}isc_result_tdns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,			 isc_task_t *task, isc_taskaction_t action, void *arg,			 dns_messageid_t *idp, dns_dispentry_t **resp){	dns_dispentry_t *res;	unsigned int bucket;	dns_messageid_t id;	int i;	isc_boolean_t ok;	dns_qid_t *qid;	REQUIRE(VALID_DISPATCH(disp));	REQUIRE(task != NULL);	REQUIRE(dest != NULL);	REQUIRE(resp != NULL && *resp == NULL);	REQUIRE(idp != NULL);	LOCK(&disp->lock);	if (disp->shutting_down == 1) {		UNLOCK(&disp->lock);		return (ISC_R_SHUTTINGDOWN);	}	if (disp->requests >= disp->maxrequests) {		UNLOCK(&disp->lock);		return (ISC_R_QUOTA);	}	/*	 * Try somewhat hard to find an unique ID.	 */	qid = DNS_QID(disp);	LOCK(&qid->lock);	id = dns_randomid(qid);	bucket = dns_hash(qid, dest, id);	ok = ISC_FALSE;	for (i = 0; i < 64; i++) {		if (bucket_search(qid, dest, id, bucket) == NULL) {			ok = ISC_TRUE;			break;		}		id += qid->qid_increment;		id &= 0x0000ffff;		bucket = dns_hash(qid, dest, id);	}	if (!ok) {		UNLOCK(&qid->lock);		UNLOCK(&disp->lock);		return (ISC_R_NOMORE);	}	res = isc_mempool_get(disp->mgr->rpool);	if (res == NULL) {		UNLOCK(&qid->lock);		UNLOCK(&disp->lock);		return (ISC_R_NOMEMORY);	}	disp->refcount++;	disp->requests++;	res->task = NULL;	isc_task_attach(task, &res->task);	res->disp = disp;	res->id = id;	res->bucket = bucket;	res->host = *dest;	res->action = action;	res->arg = arg;	res->item_out = ISC_FALSE;	ISC_LIST_INIT(res->items);	ISC_LINK_INIT(res, link);	res->magic = RESPONSE_MAGIC;	ISC_LIST_APPEND(qid->qid_table[bucket], res, link);	UNLOCK(&qid->lock);	request_log(disp, res, LVL(90),		    "attached to task %p", res->task);	if (((disp->attributes & DNS_DISPATCHATTR_UDP) != 0) ||	    ((disp->attributes & DNS_DISPATCHATTR_CONNECTED) != 0))		startrecv(disp);	UNLOCK(&disp->lock);	*idp = id;	*resp = res;	return (ISC_R_SUCCESS);}voiddns_dispatch_starttcp(dns_dispatch_t *disp) {	REQUIRE(VALID_DISPATCH(disp));	dispatch_log(disp, LVL(90), "starttcp %p", disp->task);	LOCK(&disp->lock);	disp->attributes |= DNS_DISPATCHATTR_CONNECTED;	startrecv(disp);	UNLOCK(&disp->lock);}voiddns_dispatch_removeresponse(dns_dispentry_t **resp,			    dns_dispatchevent_t **sockevent){	dns_dispatchmgr_t *mgr;	dns_dispatch_t *disp;	dns_dispentry_t *res;	dns_dispatchevent_t *ev;	unsigned int bucket;	isc_boolean_t killit;	unsigned int n;	isc_eventlist_t events;	dns_qid_t *qid;	REQUIRE(resp != NULL);	REQUIRE(VALID_RESPONSE(*resp));	res = *resp;	*resp = NULL;	disp = res->disp;	REQUIRE(VALID_DISPATCH(disp));	mgr = disp->mgr;	REQUIRE(VALID_DISPATCHMGR(mgr));	qid = DNS_QID(disp);	if (sockevent != NULL) {		REQUIRE(*sockevent != NULL);		ev = *sockevent;		*sockevent = NULL;	} else {		ev = NULL;	}	LOCK(&disp->lock);	INSIST(disp->requests > 0);	disp->requests--;	INSIST(disp->refcount > 0);	disp->refcount--;	killit = ISC_FALSE;	if (disp->refcount == 0) {		if (disp->recv_pending > 0)			isc_socket_cancel(disp->socket, disp->task,					  ISC_SOCKCANCEL_RECV);		disp->shutting_down = 1;	}	bucket = res->bucket;	LOCK(&qid->lock);	ISC_LIST_UNLINK(qid->qid_table[bucket], res, link);	UNLOCK(&qid->lock);	if (ev == NULL && res->item_out) {		/*		 * We've posted our event, but the caller hasn't gotten it		 * yet.  Take it back.		 */		ISC_LIST_INIT(events);		n = isc_task_unsend(res->task, res, DNS_EVENT_DISPATCH,				    NULL, &events);		/*		 * We had better have gotten it back.		 */		INSIST(n == 1);		ev = (dns_dispatchevent_t *)ISC_LIST_HEAD(events);	}	if (ev != NULL) {		REQUIRE(res->item_out == ISC_TRUE);		res->item_out = ISC_FALSE;		if (ev->buffer.base != NULL)			free_buffer(disp, ev->buffer.base, ev->buffer.length);		free_event(disp, ev);	}	request_log(disp, res, LVL(90), "detaching from task %p", res->task);	isc_task_detach(&res->task);	/*	 * Free any buffered requests as well	 */	ev = ISC_LIST_HEAD(res->items);	while (ev != NULL) {		ISC_LIST_UNLINK(res->items, ev, ev_link);		if (ev->buffer.base != NULL)			free_buffer(disp, ev->buffer.base, ev->buffer.length);		free_event(disp, ev);		ev = ISC_LIST_HEAD(res->items);	}	res->magic = 0;	isc_mempool_put(disp->mgr->rpool, res);	if (disp->shutting_down == 1)		do_cancel(disp);	else		startrecv(disp);	killit = destroy_disp_ok(disp);	UNLOCK(&disp->lock);	if (killit)		isc_task_send(disp->task, &disp->ctlevent);}static voiddo_cancel(dns_dispatch_t *disp) {	dns_dispatchevent_t *ev;	dns_dispentry_t *resp;	dns_qid_t *qid;	if (disp->shutdown_out == 1)		return;	qid = DNS_QID(disp);	/*	 * Search for the first response handler without packets outstanding.	 */	LOCK(&qid->lock);	for (resp = linear_first(qid);	     resp != NULL && resp->item_out != ISC_FALSE;	     /* Empty. */)		resp = linear_next(qid, resp);	/*	 * No one to send the cancel event to, so nothing to do.	 */	if (resp == NULL)		goto unlock;	/*	 * Send the shutdown failsafe event to this resp.	 */	ev = disp->failsafe_ev;	ISC_EVENT_INIT(ev, sizeof(*ev), 0, NULL, DNS_EVENT_DISPATCH,		       resp->action, resp->arg, resp, NULL, NULL);	ev->result = disp->shutdown_why;	ev->buffer.base = NULL;	ev->buffer.length = 0;	disp->shutdown_out = 1;	request_log(disp, resp, LVL(10),		    "cancel: failsafe event %p -> task %p",		    ev, resp->task);	resp->item_out = ISC_TRUE;	isc_task_send(resp->task, ISC_EVENT_PTR(&ev)); unlock:	UNLOCK(&qid->lock);}isc_socket_t *dns_dispatch_getsocket(dns_dispatch_t *disp) {	REQUIRE(VALID_DISPATCH(disp));	return (disp->socket);}isc_result_tdns_dispatch_getlocaladdress(dns_dispatch_t *disp, isc_sockaddr_t *addrp) {	REQUIRE(VALID_DISPATCH(disp));	REQUIRE(addrp != NULL);	if (disp->socktype == isc_sockettype_udp) {		*addrp = disp->local;		return (ISC_R_SUCCESS);	}	return (ISC_R_NOTIMPLEMENTED);}voiddns_dispatch_cancel(dns_dispatch_t *disp) {	REQUIRE(VALID_DISPATCH(disp));	LOCK(&disp->lock);	if (disp->shutting_down == 1) {		UNLOCK(&disp->lock);		return;	}	disp->shutdown_why = ISC_R_CANCELED;	disp->shutting_down = 1;	do_cancel(disp);	UNLOCK(&disp->lock);	return;}voiddns_dispatch_changeattributes(dns_dispatch_t *disp,			      unsigned int attributes, unsigned int mask){	REQUIRE(VALID_DISPATCH(disp));	/* XXXMLG	 * Should check for valid attributes here!	 */	LOCK(&disp->lock);	if ((mask & DNS_DISPATCHATTR_NOLISTEN) != 0) {		if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) != 0 &&		    (attributes & DNS_DISPATCHATTR_NOLISTEN) == 0) {			disp->attributes &= ~DNS_DISPATCHATTR_NOLISTEN;			startrecv(disp);		} else if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN)			   == 0 &&			   (attributes & DNS_DISPATCHATTR_NOLISTEN) != 0) {			disp->attributes |= DNS_DISPATCHATTR_NOLISTEN;			if (disp->recv_pending != 0)				isc_socket_cancel(disp->socket, disp->task,						  ISC_SOCKCANCEL_RECV);		}	}	disp->attributes &= ~mask;	disp->attributes |= (attributes & mask);	UNLOCK(&disp->lock);}voiddns_dispatch_importrecv(dns_dispatch_t *disp, isc_event_t *event) {	void *buf;	isc_socketevent_t *sevent, *newsevent;	REQUIRE(VALID_DISPATCH(disp));	REQUIRE((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) != 0);	REQUIRE(event != NULL);	sevent = (isc_socketevent_t *)event;	INSIST(sevent->n <= disp->mgr->buffersize);	newsevent = (isc_socketevent_t *)		    isc_event_allocate(disp->mgr->mctx, NULL,				      DNS_EVENT_IMPORTRECVDONE, udp_recv,				      disp, sizeof(isc_socketevent_t));	if (newsevent == NULL)		return;	buf = allocate_udp_buffer(disp);	if (buf == NULL) {		isc_event_free(ISC_EVENT_PTR(&newsevent));		return;	}	memcpy(buf, sevent->region.base, sevent->n);	newsevent->region.base = buf;	newsevent->region.length = disp->mgr->buffersize;	newsevent->n = sevent->n;	newsevent->result = sevent->result;	newsevent->address = sevent->address;	newsevent->timestamp = sevent->timestamp;	newsevent->pktinfo = sevent->pktinfo;	newsevent->attributes = sevent->attributes;		isc_task_send(disp->task, ISC_EVENT_PTR(&newsevent));}#if 0voiddns_dispatchmgr_dump(dns_dispatchmgr_t *mgr) {	dns_dispatch_t *disp;	char foo[1024];	disp = ISC_LIST_HEAD(mgr->list);	while (disp != NULL) {		isc_sockaddr_format(&disp->local, foo, sizeof(foo));		printf("\tdispatch %p, addr %s\n", disp, foo);		disp = ISC_LIST_NEXT(disp, link);	}}#endif

⌨️ 快捷键说明

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